Skip to content

Commit

Permalink
Merge pull request #2921 from stmcginnis/template-mode
Browse files Browse the repository at this point in the history
hardening: Enable setting templated file permissions
  • Loading branch information
stmcginnis authored May 4, 2023
2 parents 1749be3 + 450b56c commit 5d7c1cd
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 10 deletions.
1 change: 1 addition & 0 deletions Release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,5 @@ version = "1.14.0"
"(1.13.5, 1.14.0)" = [
"migrate_v1.14.0_kubernetes-gc-percent-type-change.lz4",
"migrate_v1.14.0_kubelet-config-settings.lz4",
"migrate_v1.14.0_k8s-services-mode.lz4",
]
8 changes: 8 additions & 0 deletions sources/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions sources/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ members = [
"api/migration/migrations/v1.13.4/add-hostname-override-metadata",
"api/migration/migrations/v1.14.0/kubernetes-gc-percent-type-change",
"api/migration/migrations/v1.14.0/kubelet-config-settings",
"api/migration/migrations/v1.14.0/k8s-services-mode",

"bottlerocket-release",

Expand Down
1 change: 1 addition & 0 deletions sources/api/apiserver/src/server/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ mod test {
hashmap!("foo".to_string() => ConfigurationFile {
path: "file".try_into().unwrap(),
template_path: "template".try_into().unwrap(),
mode: None,
})
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "k8s-services-mode"
version = "0.1.0"
authors = ["Sean McGinnis <stmcg@amazon.com>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
publish = false
# Don't rebuild crate just because of changes to README.
exclude = ["README.md"]

[dependencies]
migration-helpers = { path = "../../../migration-helpers", version = "0.1.0"}
serde_json = "1.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use migration_helpers::{common_migrations::AddSettingsMigration, migrate, Result};
use std::process;

/// Mode settings were added for a handful of the templated kubelet configuration files.
fn run() -> Result<()> {
migrate(AddSettingsMigration(&[
"configuration-files.kubelet-config.mode",
"configuration-files.kubelet-kubeconfig.mode",
"configuration-files.kubelet-bootstrap-kubeconfig.mode",
"configuration-files.kubelet-exec-start-conf.mode",
"configuration-files.credential-provider-config-yaml.mode",
]))
}

// Returning a Result from main makes it print a Debug representation of the error, but with Snafu
// we have nice Display representations of the error, so we wrap "main" (run) and print any error.
// https://github.com/shepmaster/snafu/issues/110
fn main() {
if let Err(e) = run() {
eprintln!("{}", e);
process::exit(1);
}
}
52 changes: 42 additions & 10 deletions sources/api/thar-be-settings/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ use crate::{error, Result};
use itertools::join;
use snafu::{ensure, ResultExt};
use std::collections::HashSet;
use std::fs;
use std::fs::{self, OpenOptions};
use std::io::prelude::*;
use std::os::unix::fs::OpenOptionsExt;
use std::path::{Path, PathBuf};
use std::process::Command;

const SYSTEMCTL_DAEMON_RELOAD: &str = "systemctl daemon-reload";
const DEFAULT_FILE_MODE: u32 = 0o644;

/// Query the API for ConfigurationFile data
#[allow(clippy::implicit_hasher)]
Expand Down Expand Up @@ -63,12 +66,18 @@ pub fn render_config_files(
let try_rendered = registry.render(&name, &settings);
if strict {
let rendered = try_rendered.context(error::TemplateRenderSnafu { template: name })?;
rendered_configs.push(RenderedConfigFile::new(&metadata.path, rendered));
rendered_configs.push(RenderedConfigFile::new(
&metadata.path,
rendered,
&metadata.mode,
));
} else {
match try_rendered {
Ok(rendered) => {
rendered_configs.push(RenderedConfigFile::new(&metadata.path, rendered))
}
Ok(rendered) => rendered_configs.push(RenderedConfigFile::new(
&metadata.path,
rendered,
&metadata.mode,
)),
Err(err) => warn!("Unable to render template '{}': {}", &name, err),
}
}
Expand Down Expand Up @@ -129,13 +138,15 @@ pub fn reload_config_files(rendered_configs: &[RenderedConfigFile]) -> Result<()
pub struct RenderedConfigFile {
path: PathBuf,
rendered: String,
mode: Option<String>,
}

impl RenderedConfigFile {
fn new(path: &str, rendered: String) -> RenderedConfigFile {
fn new(path: &str, rendered: String, mode: &Option<String>) -> RenderedConfigFile {
RenderedConfigFile {
path: PathBuf::from(&path),
rendered,
mode: mode.to_owned(),
}
}

Expand All @@ -148,10 +159,31 @@ impl RenderedConfigFile {
})?;
};

fs::write(&self.path, self.rendered.as_bytes()).context(error::TemplateWriteSnafu {
path: &self.path,
pathtype: "file",
})
let mut binding = OpenOptions::new();
let options = binding.write(true).create(true).mode(DEFAULT_FILE_MODE);

// See if this file has a config setting for a specific mode
if let Some(mode) = &self.mode {
let mode_int =
u32::from_str_radix(mode.as_str(), 8).context(error::TemplateModeSnafu {
path: &self.path,
mode,
})?;
options.mode(mode_int);
}

let mut file = options
.open(&self.path)
.context(error::TemplateWriteSnafu {
path: &self.path,
pathtype: "file",
})?;

file.write_all(self.rendered.as_bytes())
.context(error::TemplateWriteSnafu {
path: &self.path,
pathtype: "file",
})
}

/// Checks whether the config file needs `systemd` to reload.
Expand Down
8 changes: 8 additions & 0 deletions sources/api/thar-be-settings/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::num;
use http::StatusCode;
use snafu::Snafu;
use std::io;
Expand Down Expand Up @@ -27,6 +28,13 @@ pub enum Error {
source: io::Error,
},

#[snafu(display("Failed to set template {} to mode {}: {}", path.display(), mode, source))]
TemplateMode {
path: PathBuf,
mode: String,
source: num::ParseIntError,
},

#[snafu(display("Failed to run restart command - '{}': {}", command, source))]
CommandExecutionFailure { command: String, source: io::Error },

Expand Down
6 changes: 6 additions & 0 deletions sources/models/shared-defaults/kubernetes-services.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ template-path = "/usr/share/templates/kubelet-env"
[configuration-files.kubelet-config]
path = "/etc/kubernetes/kubelet/config"
template-path = "/usr/share/templates/kubelet-config"
mode = "0600"

[configuration-files.kubelet-kubeconfig]
path = "/etc/kubernetes/kubelet/kubeconfig"
template-path = "/usr/share/templates/kubelet-kubeconfig"
mode = "0600"

[configuration-files.kubelet-bootstrap-kubeconfig]
path = "/etc/kubernetes/kubelet/bootstrap-kubeconfig"
template-path = "/usr/share/templates/kubelet-bootstrap-kubeconfig"
mode = "0600"

[configuration-files.kubernetes-ca-crt]
path = "/etc/kubernetes/pki/ca.crt"
template-path = "/usr/share/templates/kubernetes-ca-crt"
mode = "0600"

[configuration-files.kubelet-server-crt]
path = "/etc/kubernetes/pki/kubelet-server.crt"
Expand All @@ -46,10 +50,12 @@ template-path = "/usr/share/templates/kubelet-server-key"
[configuration-files.kubelet-exec-start-conf]
path = "/etc/systemd/system/kubelet.service.d/exec-start.conf"
template-path = "/usr/share/templates/kubelet-exec-start-conf"
mode = "0600"

[configuration-files.credential-provider-config-yaml]
path = "/etc/kubernetes/kubelet/credential-provider-config.yaml"
template-path = "/usr/share/templates/credential-provider-config-yaml"
mode = "0600"

[services.static-pods]
configuration-files = []
Expand Down
2 changes: 2 additions & 0 deletions sources/models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ pub type ConfigurationFiles = HashMap<String, ConfigurationFile>;
struct ConfigurationFile {
path: SingleLineString,
template_path: SingleLineString,
#[serde(skip_serializing_if = "Option::is_none")]
mode: Option<String>,
}

///// Metadata
Expand Down

0 comments on commit 5d7c1cd

Please sign in to comment.