pub mod ca;
pub mod plumb;
pub mod policy;
pub use plumb::Plumbing;
pub use policy::{EgressSecretSpec, EgressSpec, Entry, HostPattern, Policy, SecretBinding};
use crate::client::Client;
use crate::error::Result;
use plumb::{KEY_POLICY, Props};
#[derive(Debug, Clone)]
pub struct Contribution {
pub plumbing: Plumbing,
pub nic: Props,
pub config: Props,
}
pub fn contribute(spec: &EgressSpec, project: &str, instance: &str) -> Result<Contribution> {
let network = plumb::network_name(project, instance);
let policy = Policy::from_spec(spec, &network)?;
let plumbing = Plumbing::new(project, instance, policy);
let mut config = Props::new();
config.insert(KEY_POLICY.into(), plumbing.policy_json());
config.insert(plumb::KEY_FOR.into(), plumbing.owner());
for s in &plumbing.policy.secrets {
config.insert(format!("environment.{}", s.env), s.placeholder.clone());
}
if !plumbing.policy.secrets.is_empty() {
config.extend(ca::guest_env());
}
Ok(Contribution {
nic: plumbing.nic(),
plumbing,
config,
})
}
pub fn before_apply(client: &Client, p: &Plumbing, report: &mut dyn FnMut(&str)) -> Result<()> {
if !p.policy.secrets.is_empty() {
ca::Ca::ensure(&p.network)?;
}
plumb::prepare(client, p, report)?;
Ok(())
}
pub fn after_ready(client: &Client, p: &Plumbing) -> Result<()> {
if p.policy.secrets.is_empty() {
return Ok(());
}
match ca::Ca::load(&p.network)? {
Some(ca) => ca::install(client, &p.instance, &ca),
None => Err(crate::error::Error::invalid(format!(
"{}: the egress CA is missing from this host's state directory; recreate the sandbox",
p.instance
))),
}
}