Merge pull request #6707 from Xynnn007/feat-policy-uri

agent: add container launch control parameters from kernel commandline
This commit is contained in:
Steve Horsman 2023-06-21 17:02:46 +01:00 committed by GitHub
commit 4ff3afc59d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 7 deletions

View File

@ -31,6 +31,9 @@ const HTTPS_PROXY: &str = "agent.https_proxy";
const NO_PROXY: &str = "agent.no_proxy"; const NO_PROXY: &str = "agent.no_proxy";
const ENABLE_DATA_INTEGRITY: &str = "agent.data_integrity"; const ENABLE_DATA_INTEGRITY: &str = "agent.data_integrity";
const ENABLE_SIGNATURE_VERIFICATION: &str = "agent.enable_signature_verification"; const ENABLE_SIGNATURE_VERIFICATION: &str = "agent.enable_signature_verification";
const IMAGE_POLICY_FILE: &str = "agent.image_policy";
const IMAGE_REGISTRY_AUTH_FILE: &str = "agent.image_registry_auth";
const SIMPLE_SIGNING_SIGSTORE_CONFIG: &str = "agent.simple_signing_sigstore_config";
const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info; const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info;
const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3); const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3);
@ -89,6 +92,9 @@ pub struct AgentConfig {
pub no_proxy: String, pub no_proxy: String,
pub data_integrity: bool, pub data_integrity: bool,
pub enable_signature_verification: bool, pub enable_signature_verification: bool,
pub image_policy_file: String,
pub image_registry_auth_file: String,
pub simple_signing_sigstore_config: String,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -110,6 +116,9 @@ pub struct AgentConfigBuilder {
pub no_proxy: Option<String>, pub no_proxy: Option<String>,
pub data_integrity: Option<bool>, pub data_integrity: Option<bool>,
pub enable_signature_verification: Option<bool>, pub enable_signature_verification: Option<bool>,
pub image_policy_file: Option<String>,
pub image_registry_auth_file: Option<String>,
pub simple_signing_sigstore_config: Option<String>,
} }
macro_rules! config_override { macro_rules! config_override {
@ -177,6 +186,9 @@ impl Default for AgentConfig {
no_proxy: String::from(""), no_proxy: String::from(""),
data_integrity: false, data_integrity: false,
enable_signature_verification: true, enable_signature_verification: true,
image_policy_file: String::from(""),
image_registry_auth_file: String::from(""),
simple_signing_sigstore_config: String::from(""),
} }
} }
} }
@ -215,6 +227,13 @@ impl FromStr for AgentConfig {
agent_config, agent_config,
enable_signature_verification enable_signature_verification
); );
config_override!(agent_config_builder, agent_config, image_policy_file);
config_override!(agent_config_builder, agent_config, image_registry_auth_file);
config_override!(
agent_config_builder,
agent_config,
simple_signing_sigstore_config
);
// Populate the allowed endpoints hash set, if we got any from the config file. // Populate the allowed endpoints hash set, if we got any from the config file.
if let Some(endpoints) = agent_config_builder.endpoints { if let Some(endpoints) = agent_config_builder.endpoints {
@ -339,6 +358,31 @@ impl AgentConfig {
config.enable_signature_verification, config.enable_signature_verification,
get_bool_value get_bool_value
); );
// URI of the image security file
parse_cmdline_param!(
param,
IMAGE_POLICY_FILE,
config.image_policy_file,
get_string_value
);
// URI of the registry auth file
parse_cmdline_param!(
param,
IMAGE_REGISTRY_AUTH_FILE,
config.image_registry_auth_file,
get_string_value
);
// URI of the simple signing sigstore file
// used when simple signing verification is used
parse_cmdline_param!(
param,
SIMPLE_SIGNING_SIGSTORE_CONFIG,
config.simple_signing_sigstore_config,
get_string_value
);
} }
if let Ok(addr) = env::var(SERVER_ADDR_ENV_VAR) { if let Ok(addr) = env::var(SERVER_ADDR_ENV_VAR) {
@ -521,6 +565,9 @@ mod tests {
assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT); assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT);
assert_eq!(config.container_policy_path, ""); assert_eq!(config.container_policy_path, "");
assert!(config.enable_signature_verification); assert!(config.enable_signature_verification);
assert_eq!(config.image_policy_file, "");
assert_eq!(config.image_registry_auth_file, "");
assert_eq!(config.simple_signing_sigstore_config, "");
} }
#[test] #[test]
@ -545,6 +592,9 @@ mod tests {
no_proxy: &'a str, no_proxy: &'a str,
data_integrity: bool, data_integrity: bool,
enable_signature_verification: bool, enable_signature_verification: bool,
image_policy_file: &'a str,
image_registry_auth_file: &'a str,
simple_signing_sigstore_config: &'a str,
} }
impl Default for TestData<'_> { impl Default for TestData<'_> {
@ -566,6 +616,9 @@ mod tests {
no_proxy: "", no_proxy: "",
data_integrity: false, data_integrity: false,
enable_signature_verification: true, enable_signature_verification: true,
image_policy_file: "",
image_registry_auth_file: "",
simple_signing_sigstore_config: "",
} }
} }
} }
@ -1010,6 +1063,51 @@ mod tests {
enable_signature_verification: false, enable_signature_verification: false,
..Default::default() ..Default::default()
}, },
TestData {
contents: "agent.image_policy=file:///etc/policy.json",
image_policy_file: "file:///etc/policy.json",
..Default::default()
},
TestData {
contents: "agent.image_policy=kbs:///default/security-policy/test",
image_policy_file: "kbs:///default/security-policy/test",
..Default::default()
},
TestData {
contents: "agent.image_policy=kbs://example.kbs.org/default/security-policy/test",
image_policy_file: "kbs://example.kbs.org/default/security-policy/test",
..Default::default()
},
TestData {
contents: "agent.image_registry_auth=file:///etc/auth.json",
image_registry_auth_file: "file:///etc/auth.json",
..Default::default()
},
TestData {
contents: "agent.image_registry_auth=kbs:///default/credential/test",
image_registry_auth_file: "kbs:///default/credential/test",
..Default::default()
},
TestData {
contents: "agent.image_registry_auth=kbs://example.kbs.org/default/credential/test",
image_registry_auth_file: "kbs://example.kbs.org/default/credential/test",
..Default::default()
},
TestData {
contents: "agent.simple_signing_sigstore_config=file:///etc/containers/signature/default.yml",
simple_signing_sigstore_config: "file:///etc/containers/signature/default.yml",
..Default::default()
},
TestData {
contents: "agent.simple_signing_sigstore_config=kbs:///default/sigstore-config/test",
simple_signing_sigstore_config: "kbs:///default/sigstore-config/test",
..Default::default()
},
TestData {
contents: "agent.simple_signing_sigstore_config=kbs://example.kbs.org/default/sigstore-config/test",
simple_signing_sigstore_config: "kbs://example.kbs.org/default/sigstore-config/test",
..Default::default()
},
]; ];
let dir = tempdir().expect("failed to create tmpdir"); let dir = tempdir().expect("failed to create tmpdir");
@ -1071,6 +1169,17 @@ mod tests {
"{}", "{}",
msg msg
); );
assert_eq!(d.image_policy_file, config.image_policy_file, "{}", msg);
assert_eq!(
d.image_registry_auth_file, config.image_registry_auth_file,
"{}",
msg
);
assert_eq!(
d.simple_signing_sigstore_config, config.simple_signing_sigstore_config,
"{}",
msg
);
for v in vars_to_unset { for v in vars_to_unset {
env::remove_var(v); env::remove_var(v);

View File

@ -53,12 +53,30 @@ pub struct ImageService {
} }
impl ImageService { impl ImageService {
pub fn new(sandbox: Arc<Mutex<Sandbox>>) -> Self { pub async fn new(sandbox: Arc<Mutex<Sandbox>>) -> Self {
env::set_var("CC_IMAGE_WORK_DIR", KATA_CC_IMAGE_WORK_DIR); env::set_var("CC_IMAGE_WORK_DIR", KATA_CC_IMAGE_WORK_DIR);
let mut image_client = ImageClient::default();
let image_policy_file = &AGENT_CONFIG.read().await.image_policy_file;
if !image_policy_file.is_empty() {
image_client.config.file_paths.sigstore_config = image_policy_file.clone();
}
let simple_signing_sigstore_config =
&AGENT_CONFIG.read().await.simple_signing_sigstore_config;
if !simple_signing_sigstore_config.is_empty() {
image_client.config.file_paths.sigstore_config = simple_signing_sigstore_config.clone();
}
let image_registry_auth_file = &AGENT_CONFIG.read().await.image_registry_auth_file;
if !image_registry_auth_file.is_empty() {
image_client.config.file_paths.auth_file = image_registry_auth_file.clone();
}
Self { Self {
sandbox, sandbox,
attestation_agent_started: AtomicBool::new(false), attestation_agent_started: AtomicBool::new(false),
image_client: Arc::new(Mutex::new(ImageClient::default())), image_client: Arc::new(Mutex::new(image_client)),
container_count: Arc::new(AtomicU16::new(0)), container_count: Arc::new(AtomicU16::new(0)),
} }
} }
@ -333,7 +351,7 @@ mod tests {
let logger = slog::Logger::root(slog::Discard, o!()); let logger = slog::Logger::root(slog::Discard, o!());
let s = Sandbox::new(&logger).unwrap(); let s = Sandbox::new(&logger).unwrap();
let image_service = ImageService::new(Arc::new(Mutex::new(s))); let image_service = ImageService::new(Arc::new(Mutex::new(s))).await;
for case in &cases { for case in &cases {
let mut req = image::PullImageRequest::new(); let mut req = image::PullImageRequest::new();
req.set_image(case.image.to_string()); req.set_image(case.image.to_string());

View File

@ -346,7 +346,7 @@ async fn start_sandbox(
sandbox.lock().await.sender = Some(tx); sandbox.lock().await.sender = Some(tx);
// vsock:///dev/vsock, port // vsock:///dev/vsock, port
let mut server = rpc::start(sandbox.clone(), config.server_addr.as_str(), init_mode)?; let mut server = rpc::start(sandbox.clone(), config.server_addr.as_str(), init_mode).await?;
server.start().await?; server.start().await?;
rx.await?; rx.await?;

View File

@ -1842,7 +1842,11 @@ async fn read_stream(reader: Arc<Mutex<ReadHalf<PipeStream>>>, l: usize) -> Resu
Ok(content) Ok(content)
} }
pub fn start(s: Arc<Mutex<Sandbox>>, server_address: &str, init_mode: bool) -> Result<TtrpcServer> { pub async fn start(
s: Arc<Mutex<Sandbox>>,
server_address: &str,
init_mode: bool,
) -> Result<TtrpcServer> {
let agent_service = Box::new(AgentService { let agent_service = Box::new(AgentService {
sandbox: s.clone(), sandbox: s.clone(),
init_mode, init_mode,
@ -1853,8 +1857,8 @@ pub fn start(s: Arc<Mutex<Sandbox>>, server_address: &str, init_mode: bool) -> R
let health_service = Box::new(HealthService {}) as Box<dyn health_ttrpc::Health + Send + Sync>; let health_service = Box::new(HealthService {}) as Box<dyn health_ttrpc::Health + Send + Sync>;
let health_worker = Arc::new(health_service); let health_worker = Arc::new(health_service);
let image_service = let image_service = Box::new(image_rpc::ImageService::new(s).await)
Box::new(image_rpc::ImageService::new(s)) as Box<dyn image_ttrpc::Image + Send + Sync>; as Box<dyn image_ttrpc::Image + Send + Sync>;
let aservice = agent_ttrpc::create_agent_service(agent_worker); let aservice = agent_ttrpc::create_agent_service(agent_worker);