Move monitoring.kaareskovgaard.net to new openbao setup
Some checks failed
/ dev-shell (push) Successful in 1m52s
/ rust-packages (push) Successful in 4m3s
/ check (push) Failing after 4m59s
/ terraform-providers (push) Successful in 11m1s
/ systems (push) Successful in 31m7s

This commit is contained in:
Kaare Hoff Skovgaard 2025-07-18 00:18:26 +02:00
parent 905b1096ac
commit 1f7139f793
Signed by: khs
GPG key ID: C7D890804F01E9F0
20 changed files with 367 additions and 177 deletions

View file

@ -0,0 +1,68 @@
use std::collections::BTreeSet;
use anyhow::Context as _;
use common::proc::Command;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Link {
ifname: String,
}
#[derive(Debug, Deserialize)]
struct Addr {
addr_info: Vec<AddrInfo>,
}
#[derive(Debug, Deserialize)]
struct AddrInfo {
local: String,
prefixlen: usize,
}
#[derive(Debug, Deserialize)]
struct Route {
dst: String,
gateway: Option<String>,
}
pub fn get_link_names() -> anyhow::Result<BTreeSet<String>> {
let mut proc = Command::new("ip");
proc.args(["-j", "link"]);
let out = proc.try_spawn_to_json::<Vec<Link>>()?;
Ok(out.into_iter().map(|l| l.ifname).collect())
}
pub fn has_ipv6_address(dev: &str, addr: &str) -> anyhow::Result<bool> {
let mut proc = Command::new("ip");
proc.args(["-j", "-6", "addr", "show", dev]);
let out: Vec<Addr> = proc.try_spawn_to_json()?;
let idx = addr
.char_indices()
.find_map(|(idx, ch)| if ch == '/' { Some(idx) } else { None })
.expect("Address should contain prefixlen");
let prefixlen = &addr[idx + 1..];
let addr = &addr[..idx];
let prefixlen: usize = prefixlen
.parse()
.context("Ipv6 prefixlen was not a usize")?;
Ok(out.iter().any(|a| {
a.addr_info
.iter()
.any(|a| a.local == addr && a.prefixlen == prefixlen)
}))
}
pub fn has_default_route(dev: &str, gateway: &str) -> anyhow::Result<bool> {
let mut proc = Command::new("ip");
proc.args(["-j", "-6", "route", "show", "dev", dev]);
let out: Vec<Route> = proc.try_spawn_to_json()?;
Ok(out
.iter()
.any(|r| r.dst == "default" && r.gateway.as_deref().is_some_and(|gw| gw == gateway)))
}

View file

@ -3,6 +3,7 @@ use clap::{Parser, Subcommand};
use crate::metadata::Instance;
mod iproute2;
mod metadata;
fn main() {
@ -35,6 +36,7 @@ fn configure() -> anyhow::Result<()> {
let metadata = common::curl::read_text_as_string(&metadata_api)?;
let metadata: Instance = common::yaml::from_str(&metadata)
.context("Could not parse instance metadata into expected format")?;
let link_names = iproute2::get_link_names()?;
for m in metadata.network_config.config {
for subnet in m.subnets {
match subnet {
@ -44,27 +46,32 @@ fn configure() -> anyhow::Result<()> {
address,
gateway,
} => {
let mut cmd = common::proc::Command::new("ip");
if ipv6.is_some_and(|v| v) {
cmd.arg("-6");
}
if ipv4.is_some_and(|v| v) {
cmd.arg("-4");
continue;
}
if !ipv6.is_some_and(|v| v) {
continue;
}
// Apparently the configuration used renames the eth0 device to enp1s0, I should really figure out why this happens, but for now
// this will do.
let dev_name = if m.name == "eth0" { "enp1s0" } else { &m.name };
cmd.args(["addr", "add", &address, "dev", dev_name]);
cmd.try_spawn_to_string()?;
let mut cmd = common::proc::Command::new("ip");
if ipv6.is_some_and(|v| v) {
cmd.arg("-6");
let dev_name = if m.name == "eth0" && !link_names.contains("eth0") {
"enp1s0"
} else {
&m.name
};
if !iproute2::has_ipv6_address(dev_name, &address)? {
let mut cmd = common::proc::Command::new("ip");
cmd.args(["-6", "addr", "add", &address, "dev", dev_name]);
cmd.try_spawn_to_string()?;
}
if ipv4.is_some_and(|v| v) {
cmd.arg("-4");
if !iproute2::has_default_route(dev_name, &gateway)? {
let mut cmd = common::proc::Command::new("ip");
cmd.args([
"-6", "route", "add", "default", "via", &gateway, "dev", dev_name,
]);
cmd.try_spawn_to_string()?;
}
cmd.args(["route", "add", "default", "via", &gateway, "dev", dev_name]);
cmd.try_spawn_to_string()?;
}
metadata::InstanceNetworkConfigConfigSubnet::Dhcp {} => continue,
}

View file

@ -54,8 +54,6 @@ pub enum Endpoint {
Unifi,
#[value(name = "vault")]
Vault,
#[value(name = "authentik")]
Authentik,
}
impl Endpoint {
@ -81,10 +79,6 @@ impl Endpoint {
let data = UnifiData::read_from_bao()?;
Ok(data.into())
}
Self::Authentik => {
let data = AuthentikData::read_from_bao()?;
Ok(data.into())
}
Self::Vault => {
let data = VaultData::read_from_bao()?;
Ok(data.into())
@ -152,12 +146,6 @@ entry_definition!(
&["UNIFI_USERNAME", "UNIFI_PASSWORD", "UNIFI_API"]
);
entry_definition!(VaultDataConfig, VaultData, "vault", &["VAULT_TOKEN"]);
entry_definition!(
AuthentikDataConfig,
AuthentikData,
"authentik",
&["AUTHENTIK_TOKEN", "TF_VAR_authentik_username"]
);
fn transfer() -> anyhow::Result<()> {
let openstack = OpenstackData::try_new_from_env()?;
@ -165,7 +153,6 @@ fn transfer() -> anyhow::Result<()> {
let aws = AwsData::try_new_from_env()?;
let hcloud = HcloudData::try_new_from_env()?;
let unifi = UnifiData::try_new_from_env()?;
let authentik = AuthentikData::try_new_from_env()?;
let vault = VaultData::try_new_from_env()?;
write_kv_data(openstack)?;
@ -173,7 +160,6 @@ fn transfer() -> anyhow::Result<()> {
write_kv_data(aws)?;
write_kv_data(hcloud)?;
write_kv_data(unifi)?;
write_kv_data(authentik)?;
write_kv_data(vault)?;
Ok(())
}