Compare commits

..

10 Commits

18 changed files with 268 additions and 101 deletions

2
.gitignore vendored

@ -1,3 +1,5 @@
# SPDX-License-Identifier: Unlicense
dtrfs.tar dtrfs.tar
build build
tmp tmp

24
LICENSE Normal file

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <https://unlicense.org/>

@ -1,3 +1,7 @@
<!--
SPDX-License-Identifier: Unlicense
-->
## OS template ## OS template
You will need a working OS template to work with this project. You will need a working OS template to work with this project.

66
dtrfs_api/Cargo.lock generated

@ -1,3 +1,5 @@
# SPDX-License-Identifier: Unlicense
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
@ -409,6 +411,15 @@ dependencies = [
"alloc-stdlib", "alloc-stdlib",
] ]
[[package]]
name = "bs58"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -417,9 +428,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.9.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
[[package]] [[package]]
name = "bytestring" name = "bytestring"
@ -670,7 +681,7 @@ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
"bincode", "bincode",
"bytes", "bs58",
"ed25519-dalek", "ed25519-dalek",
"lazy_static", "lazy_static",
"regex", "regex",
@ -679,9 +690,6 @@ dependencies = [
"serde", "serde",
"sev", "sev",
"sha3", "sha3",
"tokio",
"tokio-stream",
"tokio-util",
] ]
[[package]] [[package]]
@ -2085,6 +2093,21 @@ dependencies = [
"zerovec", "zerovec",
] ]
[[package]]
name = "tinyvec"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tls_codec" name = "tls_codec"
version = "0.4.1" version = "0.4.1"
@ -2108,9 +2131,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.42.0" version = "1.41.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -2120,21 +2143,9 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "tokio-macros"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.26.0" version = "0.26.0"
@ -2146,22 +2157,11 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-stream"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.13" version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",

@ -1,22 +1,21 @@
# SPDX-License-Identifier: Unlicense
[package] [package]
name = "dtrfs_api" name = "dtrfs_api"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
bs58 = "0.5.1"
anyhow = "1.0.93" anyhow = "1.0.93"
base64 = "0.22.1"
bincode = "1.3.3" bincode = "1.3.3"
regex = "1.11.1" regex = "1.11.1"
sev = { version = "4.0", default-features = false, features = ['crypto_nossl','snp'] } sev = { version = "4.0", default-features = false, features = ['crypto_nossl','snp'] }
ed25519-dalek = { version = "2.1.1", features = ["pem", "pkcs8"] } ed25519-dalek = { version = "2.1.1" }
lazy_static = "1.5.0" lazy_static = "1.5.0"
tokio = { version = "1.42.0", features = ["full"] }
tokio-util = "0.7.13"
tokio-stream = { version = "0.1.17", features = ["io-util"] }
actix-web = { version = "4.9.0", features = ["rustls-0_23"] } actix-web = { version = "4.9.0", features = ["rustls-0_23"] }
sha3 = "0.10.8" sha3 = "0.10.8"
rustls = "0.23.18" rustls = "0.23.18"
rustls-pemfile = "2.2.0" rustls-pemfile = "2.2.0"
serde = { version = "1.0.215", features = ["derive"] } serde = { version = "1.0.215", features = ["derive"] }
bytes = "1.9.0" base64 = "0.22.1"

@ -1,3 +1,5 @@
# SPDX-License-Identifier: Unlicense
reorder_impl_items = true reorder_impl_items = true
use_small_heuristics = "Max" use_small_heuristics = "Max"
merge_imports = true merge_imports = true

@ -1,9 +1,10 @@
// SPDX-License-Identifier: Unlicense
mod os; mod os;
mod snp; mod snp;
use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer}; use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer};
use base64::prelude::{Engine, BASE64_URL_SAFE}; use ed25519_dalek::{Signature, Verifier, VerifyingKey};
use ed25519_dalek::{pkcs8::DecodePublicKey, Signature, Verifier, VerifyingKey};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use rustls::{pki_types::PrivateKeyDer, ServerConfig}; use rustls::{pki_types::PrivateKeyDer, ServerConfig};
@ -45,13 +46,16 @@ fn get_cert_hash() -> [u8; 64] {
} }
fn verifying_key() -> Result<VerifyingKey, Box<dyn std::error::Error>> { fn verifying_key() -> Result<VerifyingKey, Box<dyn std::error::Error>> {
let re = Regex::new(r"detee_admin=([A-Za-z0-9+/=]+)").unwrap(); let re = Regex::new(r"detee_admin=([A-Za-z0-9]+)").unwrap();
let key_str = re.find(&CMDLINE).map(|m| m.as_str()).unwrap_or(""); let key_str = re.find(&CMDLINE).map(|m| m.as_str()).unwrap_or("");
let key_pem = format!( let key_str =
"-----BEGIN PUBLIC KEY-----\n{}\n-----END PUBLIC KEY-----\n", key_str.strip_prefix("detee_admin=").ok_or("Could not get admin key from cmdline")?;
key_str.strip_prefix("detee_admin=").ok_or("Could not get admin key from cmdline")? Ok(VerifyingKey::from_bytes(
); &bs58::decode(key_str)
Ok(VerifyingKey::from_public_key_pem(&key_pem)?) .into_vec()?
.try_into()
.map_err(|_| bs58::decode::Error::BufferTooSmall)?,
)?)
} }
fn verify(req: &HttpRequest) -> Result<(), Box<dyn std::error::Error>> { fn verify(req: &HttpRequest) -> Result<(), Box<dyn std::error::Error>> {
@ -60,8 +64,8 @@ fn verify(req: &HttpRequest) -> Result<(), Box<dyn std::error::Error>> {
.get("ed25519-signature") .get("ed25519-signature")
.ok_or_else(|| "Did not find ed25519-signature header")?; .ok_or_else(|| "Did not find ed25519-signature header")?;
let signature: &[u8] = &BASE64_URL_SAFE.decode(signature)?; let signature = bs58::decode(signature).into_vec()?;
let signature = Signature::from_bytes(signature.try_into()?); let signature = Signature::from_bytes(signature.as_slice().try_into()?);
let verifying_key = verifying_key()?; let verifying_key = verifying_key()?;
Ok(verifying_key.verify(CRT_CONTENTS.as_bytes(), &signature)?) Ok(verifying_key.verify(CRT_CONTENTS.as_bytes(), &signature)?)
} }
@ -82,6 +86,7 @@ async fn get_report() -> HttpResponse {
#[derive(Deserialize)] #[derive(Deserialize)]
struct InstallForm { struct InstallForm {
hostname: String,
url: String, url: String,
sha: String, sha: String,
keyfile: String, keyfile: String,
@ -93,8 +98,8 @@ async fn post_install_form(req: HttpRequest, form: web::Form<InstallForm>) -> Ht
if let Err(e) = verify(&req) { if let Err(e) = verify(&req) {
return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e)); return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e));
}; };
match os::encrypt_and_install_os(&form.url, &form.sha, &form.keyfile).await { match os::encrypt_and_install_os(&form.url, &form.sha, &form.keyfile, &form.hostname) {
Ok(s) => HttpResponse::Ok().streaming(s), Ok(s) => HttpResponse::Ok().body(s),
Err(e) => HttpResponse::InternalServerError().body(format!("{e:?}")), Err(e) => HttpResponse::InternalServerError().body(format!("{e:?}")),
} }
} }
@ -132,8 +137,17 @@ struct SSHKeyForm {
ssh_key: String, ssh_key: String,
} }
#[get("/ssh_key")] #[get("/server_ssh_pubkeys")]
async fn get_ssh_keys(req: HttpRequest) -> HttpResponse { async fn get_server_pubkeys() -> HttpResponse {
match os::get_server_ssh_pubkeys() {
Ok(keys) => HttpResponse::Ok().body(keys),
Err(e) => HttpResponse::InternalServerError()
.body(format!("Could not get pubkeys due to error: {e:?}\nDid you install the OS?")),
}
}
#[get("/authorized_keys")]
async fn get_authorized_keys(req: HttpRequest) -> HttpResponse {
if let Err(e) = verify(&req) { if let Err(e) = verify(&req) {
return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e)); return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e));
}; };
@ -143,13 +157,13 @@ async fn get_ssh_keys(req: HttpRequest) -> HttpResponse {
} }
} }
#[post("/ssh_key")] #[post("/authorized_keys")]
async fn post_ssh_key(req: HttpRequest, form: web::Form<SSHKeyForm>) -> HttpResponse { async fn post_authorized_keys(req: HttpRequest, form: web::Form<SSHKeyForm>) -> HttpResponse {
if let Err(e) = verify(&req) { if let Err(e) = verify(&req) {
return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e)); return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e));
}; };
let ssh_key = &form.ssh_key; let ssh_key = &form.ssh_key;
match os::add_ssh_key(ssh_key) { match os::add_authorized_key(ssh_key) {
Ok(()) => HttpResponse::Ok().body("Key added to authorized_keys"), Ok(()) => HttpResponse::Ok().body("Key added to authorized_keys"),
Err(e) => HttpResponse::BadRequest().body(format!("{e:?}")), Err(e) => HttpResponse::BadRequest().body(format!("{e:?}")),
} }
@ -183,7 +197,7 @@ async fn main() -> std::io::Result<()> {
Ok(_) => { Ok(_) => {
println!("Hot decryption successful. Booting OS..."); println!("Hot decryption successful. Booting OS...");
return Ok(()); return Ok(());
}, }
Err(e) => { Err(e) => {
println!("Hot decryption failed: {e:?}"); println!("Hot decryption failed: {e:?}");
} }
@ -194,8 +208,9 @@ async fn main() -> std::io::Result<()> {
.service(post_install_form) .service(post_install_form)
.service(post_decrypt_form) .service(post_decrypt_form)
.service(post_process_exit) .service(post_process_exit)
.service(post_ssh_key) .service(get_server_pubkeys)
.service(get_ssh_keys) .service(post_authorized_keys)
.service(get_authorized_keys)
.service(get_report) .service(get_report)
.service(homepage) .service(homepage)
}) })

@ -1,60 +1,51 @@
// SPDX-License-Identifier: Unlicense
use crate::snp::get_derived_key; use crate::snp::get_derived_key;
use bytes::Bytes;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use base64::prelude::{Engine, BASE64_URL_SAFE}; use base64::prelude::{Engine, BASE64_URL_SAFE};
use std::process::Command;
use std::{ use std::{
fs::File, fs::File,
io::{BufRead, BufReader, Write}, io::{BufRead, BufReader, Write},
path::Path, path::Path,
process::Stdio, process::Command,
}; };
const SNP_KEYFILE_PATH: &str = "/tmp/detee_snp_keyfile"; const SNP_KEYFILE_PATH: &str = "/tmp/detee_snp_keyfile";
const BACKUP_KEYFILE_PATH: &str = "/tmp/detee_backup_keyfile"; const BACKUP_KEYFILE_PATH: &str = "/tmp/detee_backup_keyfile";
pub async fn encrypt_and_install_os( pub fn encrypt_and_install_os(
install_url: &str, install_url: &str,
install_sha: &str, install_sha: &str,
keyfile: &str, keyfile: &str,
) -> Result<impl tokio_stream::Stream<Item = Result<Bytes>>> { vm_hostname: &str,
// I swear I tried my best to do without tokio ) -> Result<String> {
// It is just such a pain to do to anything without tokio let binary_keyfile = BASE64_URL_SAFE.decode(keyfile)?;
// I am sorry for the mess but I gave up after countless tries std::fs::write(BACKUP_KEYFILE_PATH, binary_keyfile)?;
use tokio::process::Command; // this path is hardcoded also in the initrd creation script
use tokio::io::{BufReader, AsyncBufReadExt}; let install_result = Command::new("/usr/lib/dtrfs/install_os.sh")
use tokio_stream::{StreamExt, wrappers::LinesStream};
let binary_keyfile = base64::engine::general_purpose::URL_SAFE.decode(keyfile)?;
// Write the decoded keyfile to the backup path asynchronously
tokio::fs::write(BACKUP_KEYFILE_PATH, &binary_keyfile).await?;
// Spawn the installation script as a child process
let mut child = Command::new("/usr/lib/dtrfs/install_os.sh")
.env("INSTALL_URL", install_url) .env("INSTALL_URL", install_url)
.env("INSTALL_SHA", install_sha) .env("INSTALL_SHA", install_sha)
.env("SNP_KEY_FILE", SNP_KEYFILE_PATH) .env("SNP_KEY_FILE", SNP_KEYFILE_PATH)
.env("ROOT_KEYFILE", BACKUP_KEYFILE_PATH) .env("ROOT_KEYFILE", BACKUP_KEYFILE_PATH)
.stdout(Stdio::piped()) .env("VM_HOSTNAME", vm_hostname)
.stderr(Stdio::piped()) .output()?;
.spawn()?;
// Take stdout and stderr from the child process if !install_result.status.success() {
let stdout = child.stdout.take().unwrap(); return Err(anyhow!(
let stderr = child.stderr.take().unwrap(); "OS installation script failed.\nScript stdout:\n{}\nScript stderr:\n{}",
String::from_utf8(install_result.stdout)
// Merge stdout and stderr into a single stream .unwrap_or("Could not grab stdout from installation script.".to_string()),
let stdout_lines = LinesStream::new(BufReader::new(stdout).lines()); String::from_utf8(install_result.stderr)
let stderr_lines = LinesStream::new(BufReader::new(stderr).lines()); .unwrap_or("Could not grab stderr from installation script.".to_string()),
let merged_stream = stdout_lines.merge(stderr_lines).map(|line_result| { ));
line_result }
.map(|line| Bytes::from(line + "\n")) Ok(format!(
.map_err(|e| anyhow::Error::new(e)) "Successfully installed OS. Script stdout:\n{}\nScript stderr:\n{}",
}); String::from_utf8(install_result.stdout)
.unwrap_or("Could not grab stdout from installation script.".to_string()),
// Return the merged stream as the HTTP response String::from_utf8(install_result.stderr)
Ok(merged_stream) .unwrap_or("Could not grab stderr from installation script.".to_string()),
))
} }
pub fn try_hot_keyfile() -> Result<()> { pub fn try_hot_keyfile() -> Result<()> {
@ -115,7 +106,7 @@ pub fn replace_hot_keyfile() -> Result<String> {
Ok("Succesfully replaced hot keyfile using SNP KDF.".to_string()) Ok("Succesfully replaced hot keyfile using SNP KDF.".to_string())
} }
pub fn add_ssh_key(key: &str) -> Result<()> { pub fn add_authorized_key(key: &str) -> Result<()> {
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
if !Path::new("/mnt/etc/os-release").try_exists().is_ok_and(|found| found == true) { if !Path::new("/mnt/etc/os-release").try_exists().is_ok_and(|found| found == true) {
return Err(anyhow!( return Err(anyhow!(
@ -155,6 +146,19 @@ pub fn add_ssh_key(key: &str) -> Result<()> {
Ok(()) Ok(())
} }
pub fn get_server_ssh_pubkeys() -> Result<String> {
let files = vec![
"/mnt/etc/ssh/ssh_host_rsa_key.pub",
"/mnt/etc/ssh/ssh_host_ecdsa_key.pub",
"/mnt/etc/ssh/ssh_host_ed25519_key.pub",
];
Ok(files
.iter()
.map(|f| std::fs::read_to_string(f))
.collect::<Result<String, std::io::Error>>()?)
}
pub fn list_ssh_keys() -> Result<String> { pub fn list_ssh_keys() -> Result<String> {
Ok(std::fs::read_to_string("/mnt/root/.ssh/authorized_keys")?) Ok(std::fs::read_to_string("/mnt/root/.ssh/authorized_keys")?)
} }

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Unlicense
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use sev::firmware::guest::{AttestationReport, DerivedKey, Firmware, GuestFieldSelect}; use sev::firmware::guest::{AttestationReport, DerivedKey, Firmware, GuestFieldSelect};
use base64::prelude::{Engine, BASE64_URL_SAFE}; use base64::prelude::{Engine, BASE64_URL_SAFE};

@ -3,6 +3,8 @@ asn1_encoder
async_tx async_tx
async_xor async_xor
atkbd atkbd
bridge
br_netfilter
cbc cbc
cdrom cdrom
crc16 crc16
@ -12,6 +14,7 @@ crc32_pclmul
crct10dif_pclmul crct10dif_pclmul
cryptd cryptd
crypto_simd crypto_simd
curve25519_x86_64
dm_bufio dm_bufio
dm_crypt dm_crypt
dm-integrity dm-integrity
@ -27,23 +30,53 @@ i2c_i801
i2c_mux i2c_mux
i2c_smbus i2c_smbus
i8042 i8042
inet_diag
intel_agp intel_agp
intel_gtt intel_gtt
intel_pmc_bxt intel_pmc_bxt
intel_rapl_common intel_rapl_common
intel_rapl_msr intel_rapl_msr
ip6table_filter
ip6table_mangle
ip6table_nat
ip6_tables
ip6_udp_tunnel
ip_set
ip_set_hash_net
iptable_filter
iptable_mangle
iptable_nat
iptable_raw
ip_tables ip_tables
ipt_REJECT
iTCO_vendor_support iTCO_vendor_support
iTCO_wdt iTCO_wdt
jbd2 jbd2
libaesgcm
libchacha20poly1305
libcrc32c
libcurve25519_generic
libps2 libps2
llc
loop loop
lpc_ich lpc_ich
mac_hid mac_hid
mbcache mbcache
mousedev mousedev
net_failover net_failover
nf_conntrack
nf_conntrack_netlink
nf_defrag_ipv4
nf_defrag_ipv6
nf_nat
nfnetlink nfnetlink
nfnetlink_acct
nfnetlink_log
nf_reject_ipv4
nf_tables
nft_chain_nat
nft_compat
overlay
parport parport
parport_pc parport_pc
pcspkr pcspkr
@ -61,9 +94,13 @@ sha256
sha256_ssse3 sha256_ssse3
sha512_ssse3 sha512_ssse3
sr_mod sr_mod
stp
tcp_diag
tee tee
trusted trusted
tsm tsm
udp_tunnel
veth
virtio_blk virtio_blk
virtio_net virtio_net
vivaldi_fmap vivaldi_fmap
@ -72,5 +109,23 @@ vmw_vsock_virtio_transport_common
vmw_vsock_vmci_transport vmw_vsock_vmci_transport
vsock vsock
vsock_loopback vsock_loopback
vxlan
wireguard
xfrm_algo
xfrm_user
xor xor
x_tables x_tables
xt_addrtype
xt_comment
xt_conntrack
xt_limit
xt_mark
xt_MASQUERADE
xt_multiport
xt_nat
xt_nfacct
xt_NFLOG
xt_physdev
xt_REDIRECT
xt_set
xt_tcpudp

@ -1,4 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" cd -- "$( dirname -- "${BASH_SOURCE[0]}" )"
source creator_exports.sh source creator_exports.sh
source creator_functions.sh source creator_functions.sh
@ -21,6 +24,7 @@ install_binary $(which blkid)
install_binary $(which fdisk) install_binary $(which fdisk)
install_binary $(which sysctl) install_binary $(which sysctl)
install_binary $(which mkfs.ext4) install_binary $(which mkfs.ext4)
install_binary $(which ssh-keygen)
install_binary $(which fsarchiver) install_binary $(which fsarchiver)
install_kmod install_kmod
install_busybox install_busybox

@ -1,4 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# root of the initrd, that will be used to create the cpio archive # root of the initrd, that will be used to create the cpio archive

@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
echo_cyan() { echo_cyan() {
echo -e "\033[0;36m$1\033[0m" echo -e "\033[0;36m$1\033[0m"
} }

@ -1,4 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
source /usr/lib/dtrfs/init_functions.sh source /usr/lib/dtrfs/init_functions.sh
install_url="/tmp/detee_install_url" install_url="/tmp/detee_install_url"

@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
load_modules() { load_modules() {
cat /load_modules.sh | bash cat /load_modules.sh | bash
} }

@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
# This script is called by dtrfs_api to install an OS. # This script is called by dtrfs_api to install an OS.
[[ -z "$INSTALL_URL" ]] && { [[ -z "$INSTALL_URL" ]] && {
@ -7,11 +9,16 @@
exit 1 exit 1
} }
[[ -z "$INSTALL_URL" ]] && { [[ -z "$INSTALL_SHA" ]] && {
echo "Did not find INSTALL_SHA env variable". echo "Did not find INSTALL_SHA env variable".
exit 2 exit 2
} }
[[ -z "$VM_HOSTNAME" ]] && {
echo "Did not find VM_HOSTNAME env variable".
exit 2
}
[[ -f "$ROOT_KEYFILE" ]] || { [[ -f "$ROOT_KEYFILE" ]] || {
echo "Did not find keyfile at the following location: $ROOT_KEYFILE" echo "Did not find keyfile at the following location: $ROOT_KEYFILE"
exit 3 exit 3
@ -55,6 +62,15 @@ fsarchiver restdir /mnt/template.fsa /
rm /mnt/template.fsa rm /mnt/template.fsa
# TODO: decide for UX if maybe we should allow user to inject fstab # TODO: decide for UX if maybe we should allow user to inject fstab
echo "" > /mnt/etc/fstab echo "" > /mnt/etc/fstab
hostname=$(cat /proc/cmdline | grep -oE 'detee_name=[0-9a-z\_\.\-]+' | cut -d '=' -f2) echo "=== Setting up guest hostname as $VM_HOSTNAME"
echo "=== Setting up guest hostname as $hostname" echo $VM_HOSTNAME > /mnt/etc/hostname
[[ -n "$hostname" ]] && echo $hostname > /mnt/etc/hostname
echo "=== Generating SSH public keys"
echo "root:x:0:0:root:/root:/bin/sh" > /etc/passwd
[[ -f "/mnt/etc/ssh/ssh_host_rsa_key" ]] ||
ssh-keygen -t rsa -f /mnt/etc/ssh/ssh_host_rsa_key -N '' > /dev/null
[[ -f "/mnt/etc/ssh/ssh_host_ecdsa_key" ]] ||
ssh-keygen -t ecdsa -f /mnt/etc/ssh/ssh_host_ecdsa_key -N '' > /dev/null
[[ -f "/mnt/etc/ssh/ssh_host_ed25519_key" ]] ||
ssh-keygen -t ed25519 -f /mnt/etc/ssh/ssh_host_ed25519_key -N '' > /dev/null
echo "=== Done! Download keys from /server_pubkeys"

@ -1,4 +1,7 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: Unlicense
cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" cd -- "$( dirname -- "${BASH_SOURCE[0]}" )"
dir="/tmp/dtrfs" dir="/tmp/dtrfs"

27
scripts/upload_to_registry.sh Executable file

@ -0,0 +1,27 @@
#!/bin/bash
# SPDX-License-Identifier: Unlicense
kernel_path="/boot/vmlinuz-linux"
dtrfs_path="$1"
dtrfs_name=$(basename $dtrfs_path)
dtrfs_sha=$(sha256sum $dtrfs_path | awk '{ print $1 }')
kernel_name="vmlinuz-linux-$(uname -r)"
kernel_sha=$(sha256sum $kernel_path | awk '{ print $1 }')
scp $dtrfs_path registry.detee.ltd:/var/www/html/${dtrfs_name}
ssh registry.detee.ltd ln -s $dtrfs_name /var/www/html/${dtrfs_sha}
scp $kernel_path registry.detee.ltd:/var/www/html/${kernel_name}
ssh registry.detee.ltd ln -s $kernel_name /var/www/html/${kernel_sha}
echo "Also add this to detee-cli/src/snp/mod.rs"
echo "
name: \"dtrfs-$(uname -r)\".to_string(),
vendor: \"ghe0\".to_string(),
dtrfs_url: \"http://registry.detee.ltd/${dtrfs_name}\".to_string(),
dtrfs_sha: \"${dtrfs_sha}\".to_string(),
kernel_url: \"http://registry.detee.ltd/${kernel_name}\".to_string(),
kernel_sha: \"${kernel_sha}\".to_string()
"