Change WireGuard keys -> configs
Setting up the WireGuard client requires several pieces of information, beyond the node private key and peer's public key. The peer endpoint address/port, peer public key, and node IP address are also required. As such, naming the resource a "key" is somewhat misleading.master
parent
3916e0eac9
commit
3f17373624
|
@ -6,7 +6,7 @@
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
|
|
||||||
use crate::k8s::{
|
use crate::k8s::{
|
||||||
assign_wireguard_key, create_bootstrap_token, unassign_wireguard_key,
|
assign_wireguard_config, create_bootstrap_token, unassign_wireguard_config,
|
||||||
};
|
};
|
||||||
use crate::model::events::*;
|
use crate::model::events::*;
|
||||||
|
|
||||||
|
@ -16,18 +16,18 @@ use crate::model::events::*;
|
||||||
/// associated with ephemeral nodes running as EC2 instances.
|
/// associated with ephemeral nodes running as EC2 instances.
|
||||||
///
|
///
|
||||||
/// When an instance starts:
|
/// When an instance starts:
|
||||||
/// 1. A WireGuard key is assigned to the instance
|
/// 1. A WireGuard config is assigned to the instance
|
||||||
/// 2. A Kubernetes bootstrap token is generated, to be used by `kubeadm` to
|
/// 2. A Kubernetes bootstrap token is generated, to be used by `kubeadm` to
|
||||||
/// add the node to the cluster.
|
/// add the node to the cluster.
|
||||||
///
|
///
|
||||||
/// When an instance is terminated:
|
/// When an instance is terminated:
|
||||||
/// 1. Any WireGuard keys assigned to the instance are unassigned
|
/// 1. Any WireGuard configs assigned to the instance are unassigned
|
||||||
pub async fn on_ec2_instance_state_change(evt: Ec2InstanceStateChange) {
|
pub async fn on_ec2_instance_state_change(evt: Ec2InstanceStateChange) {
|
||||||
debug!("EC2 instance {} is now {}", &evt.instance_id, &evt.state);
|
debug!("EC2 instance {} is now {}", &evt.instance_id, &evt.state);
|
||||||
if evt.state == "running" {
|
if evt.state == "running" {
|
||||||
if let Err(e) = assign_wireguard_key(&evt.instance_id).await {
|
if let Err(e) = assign_wireguard_config(&evt.instance_id).await {
|
||||||
error!(
|
error!(
|
||||||
"Failed to assign WireGuard key to instnce {}: {}",
|
"Failed to assign WireGuard config to instnce {}: {}",
|
||||||
&evt.instance_id, e
|
&evt.instance_id, e
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -39,9 +39,9 @@ pub async fn on_ec2_instance_state_change(evt: Ec2InstanceStateChange) {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
} else if evt.state == "terminated" {
|
} else if evt.state == "terminated" {
|
||||||
if let Err(e) = unassign_wireguard_key(&evt.instance_id).await {
|
if let Err(e) = unassign_wireguard_config(&evt.instance_id).await {
|
||||||
error!(
|
error!(
|
||||||
"Failed to unassign WireGuard key from instance: {}: {}",
|
"Failed to unassign WireGuard config from instance: {}: {}",
|
||||||
&evt.instance_id, e
|
&evt.instance_id, e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
57
src/k8s.rs
57
src/k8s.rs
|
@ -157,40 +157,48 @@ impl Into<Secret> for BootstrapToken {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign an existing WireGuard key to the specified EC2 instance
|
/// Assign an existing WireGuard configuration to the specified EC2 instance
|
||||||
///
|
///
|
||||||
/// This function finds the first unused WireGuard key, stored as a Kubernetes
|
/// This function finds the first unused WireGuard client configuration, stored
|
||||||
/// Secret resource, and assigns it to the specified EC2 instance. Keys are
|
/// as a Kubernetes Secret resource, and assigns it to the specified EC2
|
||||||
/// assigned by setting the `dynk8s.du5t1n.me/ec2-instance-id` label in the
|
/// instance. Configs are assigned by setting the
|
||||||
/// Secret resource's metadata.
|
/// `dynk8s.du5t1n.me/ec2-instance-id` label in the Secret resource's metadata.
|
||||||
///
|
///
|
||||||
/// Secret resources for WireGuard keys have a *type* of
|
/// Secret resources for WireGuard configuration have a *type* of
|
||||||
/// `dynk8s.du5t1n.me/wireguard-key`. They must be created ahead of time and
|
/// `dynk8s.du5t1n.me/wireguard-config`. The Secret's `data` field must
|
||||||
/// must refer to working keys already configured on the WireGuard server.
|
/// contain a `wireguard-config` property, which contains the WireGuard client
|
||||||
pub async fn assign_wireguard_key(
|
/// configuration the node should use. Configs must be created ahead of time
|
||||||
|
/// and must refer to working keys already configured on the WireGuard server.
|
||||||
|
pub async fn assign_wireguard_config(
|
||||||
instance_id: &str,
|
instance_id: &str,
|
||||||
) -> Result<(), kube::Error> {
|
) -> Result<(), kube::Error> {
|
||||||
let client = Client::try_default().await?;
|
let client = Client::try_default().await?;
|
||||||
let secrets: Api<Secret> = Api::default_namespaced(client);
|
let secrets: Api<Secret> = Api::default_namespaced(client);
|
||||||
debug!(
|
debug!(
|
||||||
"Checking for WireGuard keys already assigned to instance {}",
|
"Checking for WireGuard configs already assigned to instance {}",
|
||||||
instance_id
|
instance_id
|
||||||
);
|
);
|
||||||
let lp = ListParams::default()
|
let lp = ListParams::default()
|
||||||
.fields("type=dynk8s.du5t1n.me/wireguard-key")
|
.fields("type=dynk8s.du5t1n.me/wireguard-config")
|
||||||
.labels(&format!("dynk8s.du5t1n.me/ec2-instance-id={}", instance_id));
|
.labels(&format!("dynk8s.du5t1n.me/ec2-instance-id={}", instance_id));
|
||||||
let res = secrets.list(&lp).await?;
|
let res = secrets.list(&lp).await?;
|
||||||
if !res.items.is_empty() {
|
if !res.items.is_empty() {
|
||||||
info!("WireGuard key already assigned to instance {}", instance_id);
|
info!(
|
||||||
|
"WireGuard config already assigned to instance {}",
|
||||||
|
instance_id
|
||||||
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
debug!("Looking for available WireGuard keys");
|
debug!("Looking for available WireGuard configs");
|
||||||
let lp = ListParams::default()
|
let lp = ListParams::default()
|
||||||
.fields("type=dynk8s.du5t1n.me/wireguard-key")
|
.fields("type=dynk8s.du5t1n.me/wireguard-config")
|
||||||
.labels("dynk8s.du5t1n.me/ec2-instance-id=");
|
.labels("dynk8s.du5t1n.me/ec2-instance-id=");
|
||||||
let res = secrets.list(&lp).await?;
|
let res = secrets.list(&lp).await?;
|
||||||
if res.items.is_empty() {
|
if res.items.is_empty() {
|
||||||
error!("No WireGuard keys available for instance {}", &instance_id);
|
error!(
|
||||||
|
"No WireGuard config available for instance {}",
|
||||||
|
&instance_id
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
if let Some(name) = &res.items[0].metadata.name {
|
if let Some(name) = &res.items[0].metadata.name {
|
||||||
let mut labels = BTreeMap::<String, String>::new();
|
let mut labels = BTreeMap::<String, String>::new();
|
||||||
|
@ -204,7 +212,7 @@ pub async fn assign_wireguard_key(
|
||||||
let pp = PatchParams::apply(env!("CARGO_PKG_NAME")).force();
|
let pp = PatchParams::apply(env!("CARGO_PKG_NAME")).force();
|
||||||
secrets.patch(&name, &pp, &patch).await?;
|
secrets.patch(&name, &pp, &patch).await?;
|
||||||
info!(
|
info!(
|
||||||
"Assigned WireGuard key {} to instance {}",
|
"Assigned WireGuard config {} to instance {}",
|
||||||
name, &instance_id
|
name, &instance_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -212,21 +220,24 @@ pub async fn assign_wireguard_key(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unassign all WireGuard keys from the specified EC2 instance
|
/// Unassign all WireGuard configs from the specified EC2 instance
|
||||||
///
|
///
|
||||||
/// This function finds all WireGuard keys, stored as Kubernetes Secret
|
/// This function finds all WireGuard configs, stored as Kubernetes Secret
|
||||||
/// resources, associated with the specified EC2 instance and unassigns them.
|
/// resources, associated with the specified EC2 instance and unassigns them.
|
||||||
/// Unassigned keys have the `dynk8s.du5t1n.me/ec2-instance-id` label set to
|
/// Unassigned configs have the `dynk8s.du5t1n.me/ec2-instance-id` label set to
|
||||||
/// the empty string.
|
/// the empty string.
|
||||||
pub async fn unassign_wireguard_key(
|
pub async fn unassign_wireguard_config(
|
||||||
instance_id: &str,
|
instance_id: &str,
|
||||||
) -> Result<(), kube::Error> {
|
) -> Result<(), kube::Error> {
|
||||||
let client = Client::try_default().await?;
|
let client = Client::try_default().await?;
|
||||||
let secrets: Api<Secret> = Api::default_namespaced(client);
|
let secrets: Api<Secret> = Api::default_namespaced(client);
|
||||||
let lp = ListParams::default()
|
let lp = ListParams::default()
|
||||||
.fields("type=dynk8s.du5t1n.me/wireguard-key")
|
.fields("type=dynk8s.du5t1n.me/wireguard-config")
|
||||||
.labels(&format!("dynk8s.du5t1n.me/ec2-instance-id={}", instance_id));
|
.labels(&format!("dynk8s.du5t1n.me/ec2-instance-id={}", instance_id));
|
||||||
info!("Unassigning WireGuard keys from instance {}", instance_id);
|
info!(
|
||||||
|
"Unassigning WireGuard configs from instance {}",
|
||||||
|
instance_id
|
||||||
|
);
|
||||||
for s in secrets.list(&lp).await? {
|
for s in secrets.list(&lp).await? {
|
||||||
if let Some(name) = &s.metadata.name {
|
if let Some(name) = &s.metadata.name {
|
||||||
let mut labels = BTreeMap::<String, String>::new();
|
let mut labels = BTreeMap::<String, String>::new();
|
||||||
|
@ -238,7 +249,7 @@ pub async fn unassign_wireguard_key(
|
||||||
let pp = PatchParams::apply(env!("CARGO_PKG_NAME")).force();
|
let pp = PatchParams::apply(env!("CARGO_PKG_NAME")).force();
|
||||||
secrets.patch(&name, &pp, &patch).await?;
|
secrets.patch(&name, &pp, &patch).await?;
|
||||||
info!(
|
info!(
|
||||||
"Unassigned WireGuard key {} from instance {}",
|
"Unassigned WireGuard config {} from instance {}",
|
||||||
name, &instance_id
|
name, &instance_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue