Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Making issuers & secret optional #68

Merged
merged 3 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,15 @@ metadata:
spec:
# The number of wasmCloud host pods to run
hostReplicas: 2
# The cluster issuers to use for each host
issuers:
# This needs to be the public key of a cluster seed generated by
# `wash keys gen cluster`
- CDK...
# The lattice to connect the hosts to
lattice: 83a5b52e-17cf-4080-bac8-f844099f142e
# Additional labels to apply to the host other than the defaults set in the operator
hostLabels:
some-label: value
# The address to connect to nats
# The address to connect to nats
natsAddress: nats://nats-cluster.default.svc.cluster.local
# Which wasmCloud version to use
version: 1.0.2
# The name of a secret in the same namespace that provides the required secrets.
secretName: my-wasmcloud-cluster
# Enable the following to run the wasmCloud hosts as a DaemonSet
#daemonset: true
# The name of the image pull secret to use with wasmCloud hosts so that they
Expand All @@ -47,13 +40,9 @@ apiVersion: v1
kind: Secret
metadata:
name: my-wasmcloud-cluster
stringData:
# You can generate this with wash:
# `wash keys gen cluster`
WASMCLOUD_CLUSTER_SEED: <seed>
#data:
# Only required if using a NATS creds file
# nats.creds: <creds file>
# Only required if using a NATS creds file
# nats.creds: <creds file>
```

The operator will fail to provision the wasmCloud Deployment if any of these
Expand Down Expand Up @@ -227,7 +216,6 @@ data:
include [Kind](https://kind.sigs.k8s.io/) or Docker Desktop.
- `RUST_LOG=info cargo run`


## Types crate

This repo stores the types for any CRDs used by the operator in a separate
Expand Down
10 changes: 5 additions & 5 deletions crates/types/src/v1alpha1/wasmcloud_host_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ pub struct WasmCloudHostConfigSpec {
/// The number of replicas to use for the wasmCloud host Deployment.
#[serde(default = "default_host_replicas")]
pub host_replicas: u32,
/// A list of cluster issuers to use when provisioning hosts. See
/// DEPRECATED: A list of cluster issuers to use when provisioning hosts. See
/// https://wasmcloud.com/docs/deployment/security/zero-trust-invocations for more information.
pub issuers: Vec<String>,
#[deprecated(since = "0.3.1", note = "Removed in wasmcloud 1.0.0")]
pub issuers: Option<Vec<String>>,
lxfontes marked this conversation as resolved.
Show resolved Hide resolved
/// The lattice to use for these hosts.
pub lattice: String,
/// An optional set of labels to apply to these hosts.
Expand All @@ -37,9 +38,8 @@ pub struct WasmCloudHostConfigSpec {
/// If not provided, the default upstream image will be used.
/// If provided, it should be fully qualified by including the image tag.
pub nats_leaf_image: Option<String>,
/// The name of a secret containing the primary cluster issuer key along with an optional set
/// of NATS credentials.
pub secret_name: String,
/// Optional. The name of a secret containing a set of NATS credentials under 'nats.creds' key.
pub secret_name: Option<String>,
lxfontes marked this conversation as resolved.
Show resolved Hide resolved
/// Enable structured logging for host logs.
pub enable_structured_logging: Option<bool>,
/// Name of a secret containing the registry credentials
Expand Down
4 changes: 0 additions & 4 deletions sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ metadata:
namespace: default
spec:
hostReplicas: 1
issuers:
- CDKF6OKPOBQKAX57UOXO7SCHURTOZWKWIVPC2HFJTGFXY5VJX44ECEHH
# The lattice to connect the hosts to
lattice: default
# Additional labels to apply to the host other than the defaults set in the controller
Expand All @@ -15,8 +13,6 @@ spec:
cluster: kind
# Which wasmCloud version to use
version: "1.0.2"
# The name of a secret in the same namespace that provides the required secrets.
secretName: cluster-secrets
logLevel: INFO
natsAddress: nats://nats-cluster.default.svc.cluster.local
################################################
Expand Down
169 changes: 66 additions & 103 deletions src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use futures::StreamExt;
use handlebars::Handlebars;
use k8s_openapi::api::apps::v1::{DaemonSet, DaemonSetSpec, Deployment, DeploymentSpec};
use k8s_openapi::api::core::v1::{
ConfigMap, ConfigMapVolumeSource, Container, ContainerPort, EnvVar, EnvVarSource, ExecAction,
Lifecycle, LifecycleHandler, Pod, PodSpec, PodTemplateSpec, Secret, SecretKeySelector,
SecretVolumeSource, Service, ServiceAccount, ServicePort, ServiceSpec, Volume, VolumeMount,
ConfigMap, ConfigMapVolumeSource, Container, ContainerPort, EnvVar, ExecAction, Lifecycle,
LifecycleHandler, Pod, PodSpec, PodTemplateSpec, Secret, SecretVolumeSource, Service,
ServiceAccount, ServicePort, ServiceSpec, Volume, VolumeMount,
};
use k8s_openapi::api::rbac::v1::{PolicyRule, Role, RoleBinding, RoleRef, Subject};
use k8s_openapi::apimachinery::pkg::apis::meta::v1::LabelSelector;
Expand Down Expand Up @@ -56,7 +56,6 @@ pub struct Context {

#[derive(Clone, Default)]
pub struct Secrets {
pub wasmcloud_cluster_seed: String,
pub nats_creds: Option<String>,
}

Expand All @@ -69,18 +68,9 @@ impl Secrets {
);
};
let data = secret.data.as_ref().unwrap();
let wasmcloud_cluster_seed = data.get("WASMCLOUD_CLUSTER_SEED");
let nats_creds = data.get("nats.creds");

if wasmcloud_cluster_seed.is_none() {
bail!(
"Secret {} has no WASMCLOUD_CLUSTER_SEED",
secret.metadata.name.as_ref().unwrap()
);
};

Ok(Self {
wasmcloud_cluster_seed: from_utf8(&wasmcloud_cluster_seed.unwrap().0)?.to_string(),
nats_creds: match &nats_creds {
Some(c) => from_utf8(&c.0).ok().map(|s| s.to_string()),
None => None,
Expand Down Expand Up @@ -119,33 +109,37 @@ async fn reconcile_crd(config: &WasmCloudHostConfig, ctx: Arc<Context>) -> Resul
let name = config.name_any();
let config: Api<WasmCloudHostConfig> = Api::namespaced(kube_client.clone(), &ns);
let mut cfg = config.get(&name).await?;
let secrets = Api::<Secret>::namespaced(kube_client, &ns);
let secrets_api = Api::<Secret>::namespaced(kube_client, &ns);

let secret = secrets.get(&cfg.spec.secret_name).await.map_err(|e| {
warn!("Failed to read secrets: {}", e);
e
})?;
let s = Secrets::from_k8s_secret(&secret).map_err(|e| {
warn!("Failed to read secrets: {}", e);
Error::SecretError(format!(
"Failed to read all secrets from {}: {}",
secret.metadata.name.unwrap(),
let mut secrets = Secrets::default();

if let Some(secret_name) = &cfg.spec.secret_name {
let kube_secrets = secrets_api.get(secret_name).await.map_err(|e| {
warn!("Failed to read secrets: {}", e);
e
))
})?;
})?;
secrets = Secrets::from_k8s_secret(&kube_secrets).map_err(|e| {
warn!("Failed to read secrets: {}", e);
Error::SecretError(format!(
"Failed to read all secrets from {}: {}",
kube_secrets.metadata.name.unwrap(),
e
))
})?;

if let Err(e) = configmap(&cfg, ctx.clone(), s.nats_creds.is_some()).await {
if let Some(nats_creds) = &secrets.nats_creds {
if let Err(e) = store_nats_creds(&cfg, ctx.clone(), nats_creds.clone()).await {
warn!("Failed to reconcile secret: {}", e);
return Err(e);
};
}
}

if let Err(e) = configmap(&cfg, ctx.clone(), secrets.nats_creds.is_some()).await {
warn!("Failed to reconcile configmap: {}", e);
return Err(e);
};

if let Some(nats_creds) = &s.nats_creds {
if let Err(e) = store_nats_creds(&cfg, ctx.clone(), nats_creds.clone()).await {
warn!("Failed to reconcile secret: {}", e);
return Err(e);
};
}

// TODO(protochron) these could be split out into separate functions.
if let Err(e) = configure_auth(&cfg, ctx.clone()).await {
warn!("Failed to configure auth: {}", e);
Expand All @@ -162,7 +156,7 @@ async fn reconcile_crd(config: &WasmCloudHostConfig, ctx: Arc<Context>) -> Resul
return Err(e);
};

let nc = s.nats_creds.map(SecretString::new);
let nc = secrets.nats_creds.map(SecretString::new);
let apps = crate::resources::application::list_apps(
&cfg.spec.nats_address,
&cfg.spec.nats_client_port,
Expand Down Expand Up @@ -257,18 +251,6 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc<Context>) -> PodTemplate
let labels = pod_labels(config);

let mut wasmcloud_env = vec![
EnvVar {
name: "WASMCLOUD_CLUSTER_SEED".to_string(),
value_from: Some(EnvVarSource {
secret_key_ref: Some(SecretKeySelector {
name: Some(config.spec.secret_name.clone()),
key: "WASMCLOUD_CLUSTER_SEED".to_string(),
..Default::default()
}),
..Default::default()
}),
..Default::default()
},
EnvVar {
name: "WASMCLOUD_STRUCTURED_LOGGING_ENABLED".to_string(),
value: Some(
Expand Down Expand Up @@ -301,11 +283,6 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc<Context>) -> PodTemplate
value: Some(config.spec.lattice.clone()),
..Default::default()
},
EnvVar {
name: "WASMCLOUD_CLUSTER_ISSUERS".to_string(),
value: Some(config.spec.issuers.join(",")),
..Default::default()
},
EnvVar {
name: "WASMCLOUD_NATS_HOST".to_string(),
value: Some("127.0.0.1".to_string()),
Expand Down Expand Up @@ -417,6 +394,42 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc<Context>) -> PodTemplate
None => "nats:2.10-alpine".to_string(),
};

let mut volumes = vec![Volume {
name: "nats-config".to_string(),
config_map: Some(ConfigMapVolumeSource {
name: Some(config.name_any()),
..Default::default()
}),
..Default::default()
}];

let mut volume_mounts = vec![VolumeMount {
name: "nats-config".to_string(),
mount_path: "/nats/nats.conf".to_string(),
read_only: Some(true),
sub_path: Some("nats.conf".to_string()),
..Default::default()
}];

if let Some(secret_name) = &config.spec.secret_name {
volumes.push(Volume {
name: "nats-creds".to_string(),
secret: Some(SecretVolumeSource {
secret_name: Some(secret_name.clone()),
..Default::default()
}),
..Default::default()
});

volume_mounts.push(VolumeMount {
name: "nats-creds".to_string(),
mount_path: "/nats/nats.creds".to_string(),
sub_path: Some("nats.creds".to_string()),
read_only: Some(true),
..Default::default()
});
}

let containers = vec![
Container {
name: "nats-leaf".to_string(),
Expand All @@ -442,22 +455,7 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc<Context>) -> PodTemplate
..Default::default()
}),
resources: nats_resources,
volume_mounts: Some(vec![
VolumeMount {
name: "nats-config".to_string(),
mount_path: "/nats/nats.conf".to_string(),
read_only: Some(true),
sub_path: Some("nats.conf".to_string()),
..Default::default()
},
VolumeMount {
name: "nats-creds".to_string(),
mount_path: "/nats/nats.creds".to_string(),
sub_path: Some("nats.creds".to_string()),
read_only: Some(true),
..Default::default()
},
]),
volume_mounts: Some(volume_mounts),
..Default::default()
},
Container {
Expand All @@ -471,24 +469,6 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc<Context>) -> PodTemplate
},
];

let mut volumes = vec![
Volume {
name: "nats-config".to_string(),
config_map: Some(ConfigMapVolumeSource {
name: Some(config.name_any()),
..Default::default()
}),
..Default::default()
},
Volume {
name: "nats-creds".to_string(),
secret: Some(SecretVolumeSource {
secret_name: Some(config.spec.secret_name.clone()),
..Default::default()
}),
..Default::default()
},
];
let service_account = config.name_any();
let mut template = PodTemplateSpec {
metadata: Some(ObjectMeta {
Expand All @@ -498,24 +478,7 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc<Context>) -> PodTemplate
spec: Some(PodSpec {
service_account: Some(config.name_any()),
containers: containers.clone(),
volumes: Some(vec![
Volume {
name: "nats-config".to_string(),
config_map: Some(ConfigMapVolumeSource {
name: Some(config.name_any()),
..Default::default()
}),
..Default::default()
},
Volume {
name: "nats-creds".to_string(),
secret: Some(SecretVolumeSource {
secret_name: Some(config.spec.secret_name.clone()),
..Default::default()
}),
..Default::default()
},
]),
volumes: Some(volumes.clone()),
lxfontes marked this conversation as resolved.
Show resolved Hide resolved
..Default::default()
}),
};
Expand Down
Loading