summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2022-11-05 11:03:38 +0000
committerLars Wirzenius <liw@liw.fi>2022-11-05 11:03:38 +0000
commit88cb610a7e45cfd860ded97a0ab6c5e1d21d1967 (patch)
tree49c6f6e9acaf6427890bf5f2d39bd9fc7ad9b636
parentaa392fe14538fd51b6a39b91ddf3a7357e7b0994 (diff)
parent2fa8f7c0e765b4f58d0a27fe4b20a8afa45a59da (diff)
downloadvmadm-88cb610a7e45cfd860ded97a0ab6c5e1d21d1967.tar.gz
Merge branch 'liw/refactor' into 'main'
change cloud-init Python script to be separate, change pathnames to be compaitble with sshd role See merge request larswirzenius/vmadm!64
-rw-r--r--build.rs11
-rw-r--r--cloud-init.py123
-rw-r--r--src/cloudinit.rs95
3 files changed, 136 insertions, 93 deletions
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..278a7c6
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,11 @@
+use std::fs::{read, write};
+use std::path::PathBuf;
+
+fn main() {
+ let py = read("cloud-init.py").unwrap();
+ let py = String::from_utf8_lossy(&py).to_string();
+
+ let mut path: PathBuf = std::env::var("OUT_DIR").unwrap().into();
+ path.push("cloud-init.rs");
+ write(&path, &format!("r#\"{}\"#\n", py)).unwrap();
+}
diff --git a/cloud-init.py b/cloud-init.py
new file mode 100644
index 0000000..21d8ff9
--- /dev/null
+++ b/cloud-init.py
@@ -0,0 +1,123 @@
+import os
+import yaml
+
+HOST_ID_CONF = "host_id.conf"
+USER_CA_CONF = "user_id.conf"
+USER_CA_KEYS = "user-ca-keys"
+AUTH_KEYS_CONF = "authorized_keys.conf"
+
+ETC = "/etc/ssh"
+CONFIG = "sshd_config"
+CONFIG_D = "sshd_config.d"
+LOGFILE = "/tmp/vmadm.script"
+USER_DATA = "/var/lib/cloud/instance/user-data.txt"
+
+
+def etc_join(*paths):
+ return os.path.join(etc, *paths)
+
+
+def log(msg):
+ logfile.write(msg)
+ logfile.write("\n")
+ logfile.flush()
+
+
+logfile = open(LOGFILE, "w")
+log("vmadm cloud-init script starting")
+
+if os.environ.get("VMADM_TESTING"):
+ filename = "smoke/user-data"
+ etc = "x"
+else:
+ filename = USER_DATA
+ etc = ETC
+
+key_types = ("rsa", "dsa", "ecdsa", "ed25519")
+
+log(f"loading user-data from {filename}")
+obj = yaml.safe_load(open(filename))
+
+ssh_keys = obj.get("ssh_keys", {})
+user_ca_pubkey = obj.get("user_ca_pubkey", {})
+allow_authorized_keys = obj.get("allow_authorized_keys", True)
+
+keys = []
+certs = []
+
+for key_type in key_types:
+ filename = etc_join(f"ssh_host_{key_type}_key.pub")
+ if os.path.exists(filename):
+ log(f"removing {filename}")
+ os.remove(filename)
+ else:
+ log(f"file {filename} does not exist")
+
+for key_type in key_types:
+ key = ssh_keys.get(f"{key_type}_private")
+ cert = ssh_keys.get(f"{key_type}_certificate")
+ log(f"key {key_type} {key}")
+ log(f"cert {key_type} {cert }")
+
+ if key:
+ filename = etc_join(f"ssh_host_{key_type}_key")
+ log(f"writing key {filename}")
+ keys.append(filename)
+ with open(filename, "w") as f:
+ f.write(key)
+
+ if cert:
+ filename = etc_join(f"ssh_host_{key_type}_key-cert.pub")
+ log(f"writing cert {filename}")
+ certs.append(filename)
+ with open(filename, "w") as f:
+ f.write(cert)
+
+user_ca_filename = etc_join(USER_CA_KEYS)
+if user_ca_pubkey:
+ with open(user_ca_filename, "w") as f:
+ f.write(user_ca_pubkey)
+
+config = etc_join(CONFIG)
+data = ""
+if os.path.exists(config):
+ data = open(config).read()
+
+with open(config, "w") as f:
+ f.write(data)
+
+log(f"configuring sshd {config}")
+log(f"keys {keys}")
+log(f"certs {certs}")
+
+config_d = etc_join(CONFIG_D)
+log(f"config.d {CONFIG_D}")
+if not os.path.exists(config_d):
+ log(f"mkdir {config_d}")
+ os.mkdir(config_d)
+
+host_id_conf = etc_join(CONFIG_D, HOST_ID_CONF)
+log(f"write {host_id_conf}")
+with open(host_id_conf, "w") as f:
+ for filename in keys:
+ log(f"hostkey {filename}")
+ f.write(f"hostkey {filename}\n")
+ for filename in certs:
+ log(f"hostcert {filename}")
+ f.write(f"hostcertificate {filename}\n")
+
+if user_ca_pubkey:
+ user_ca_conf = etc_join(CONFIG_D, USER_CA_CONF)
+ log(f"write {user_ca_conf}")
+ with open(user_ca_conf, "w") as f:
+ log(f"trustedusercakeys {user_ca_filename}")
+ f.write(f"trustedusercakeys {user_ca_filename}\n")
+
+if not allow_authorized_keys:
+ authz_keys_conf = etc_join(CONFIG_D, AUTHZ_KEYS_CONF)
+ log(f"write {authz_keys_conf}")
+ with open(auth_keys_conf, "w") as f:
+ f.write("authorizedkeysfile none\n")
+
+log("vmadm cloud-init script ending")
+logfile.close()
diff --git a/src/cloudinit.rs b/src/cloudinit.rs
index 9d14538..6057966 100644
--- a/src/cloudinit.rs
+++ b/src/cloudinit.rs
@@ -17,98 +17,7 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use tempfile::tempdir;
-const SCRIPT: &str = r#"
-import os
-import yaml
-
-
-def log(msg):
- logfile.write(msg)
- logfile.write("\n")
- logfile.flush()
-
-
-logfile = open("/tmp/vmadm.script", "w")
-log("vmadm cloud-init script starting")
-
-if os.environ.get("VMADM_TESTING"):
- filename = "smoke/user-data"
- etc = "x"
-else:
- filename = "/var/lib/cloud/instance/user-data.txt"
- etc = "/etc/ssh"
-
-key_types = ("rsa", "dsa", "ecdsa", "ed25519")
-
-log(f"loading user-data from {filename}")
-obj = yaml.safe_load(open(filename))
-
-ssh_keys = obj.get("ssh_keys", {})
-user_ca_pubkey = obj.get("user_ca_pubkey", {})
-allow_authorized_keys = obj.get("allow_authorized_keys", True)
-
-keys = []
-certs = []
-
-for key_type in key_types:
- filename = os.path.join(etc, f"ssh_host_{key_type}_key.pub")
- if os.path.exists(filename):
- log(f"removing {filename}")
- os.remove(filename)
- else:
- log(f"file {filename} does not exist")
-
-for key_type in key_types:
- key = ssh_keys.get(f"{key_type}_private")
- cert = ssh_keys.get(f"{key_type}_certificate")
- log(f"key {key_type} {key}")
- log(f"cert {key_type} {cert }")
-
- if key:
- filename = os.path.join(etc, f"ssh_host_{key_type}_key")
- log(f"writing key {filename}")
- keys.append(filename)
- with open(filename, "w") as f:
- f.write(key)
-
- if cert:
- filename = os.path.join(etc, f"ssh_host_{key_type}_key-cert.pub")
- log(f"writing cert {filename}")
- certs.append(filename)
- with open(filename, "w") as f:
- f.write(cert)
-
-user_ca_filename = os.path.join(etc, "user-ca-keys")
-if user_ca_pubkey:
- with open(user_ca_filename, "w") as f:
- f.write(user_ca_pubkey)
-
-config = os.path.join(etc, "sshd_config")
-data = ""
-if os.path.exists(config):
- data = open(config).read()
-
-log(f"configuring sshd {config}")
-log(f"keys {keys}")
-log(f"certs {certs}")
-
-with open(config, "w") as f:
- for filename in keys:
- log(f"hostkey {filename}")
- f.write(f"hostkey {filename}\n")
- for filename in certs:
- log(f"hostcert {filename}")
- f.write(f"hostcertificate {filename}\n")
- if user_ca_pubkey:
- log(f"trustedusercakeys {user_ca_filename}")
- f.write(f"trustedusercakeys {user_ca_filename}\n")
- if not allow_authorized_keys:
- f.write("authorizedkeysfile none\n")
- f.write(data)
-
-log("vmadm cloud-init script ending")
-logfile.close()
-"#;
+const SCRIPT: &str = include!(concat!(env!("OUT_DIR"), "/cloud-init.rs"));
/// Errors from this module.
#[derive(Debug, thiserror::Error)]
@@ -198,7 +107,7 @@ struct Userdata {
impl Userdata {
fn from(spec: &Specification) -> Result<Self, CloudInitError> {
let user_ca_pubkey = if let Some(filename) = &spec.user_ca_pubkey {
- let data = std::fs::read(&filename)
+ let data = std::fs::read(filename)
.map_err(|err| CloudInitError::ReadError(filename.to_path_buf(), err))?;
Some(String::from_utf8(data)?)
} else {