Skip to content

Commit

Permalink
kbs: Add splitapi plugin
Browse files Browse the repository at this point in the history
This plugin generates credentials (keys and certificates) for
both the API proxy server (required for
kata-containers/kata-containers#9159 and
kata-containers/kata-containers#9752) and the workload owner.
This plugin also delivers the credentials to a sandbox (i.e.,
confidential PODs or VMs), specifically to the kata agent to
initiate the SplitAPI proxy server so that a workload owner
can communicate with the proxy server using a secure tunnel.

The IPv4 address, name, and the ID of the sandbox must be
provided in the query string to obtain the credential
resources from the kbs.

After receiving the credential request, the splitapi plugin
will create a key pair for the server and client and sign them
using the self-signed CA. The generated ca.crt, server.crt, and
server.key are stored in a directory specific to the sandbox
(the caller) and returned to the caller. In addition, ca.key,
client.key, and client.crt are also generated and stored to that
particular directory specific to the sandbox (i.e., caller).

During the credential generation, a sandbox directory mapper
creates a unique directory specific to the sandbox (i.e., the
caller). The mapper creates the unique directory using the
sandbox parameters passed in the query string. A mapping file is
also maintained to store the mapping between the sandbox name
and the unique directory created for the sandbox.

The splitapi plugin itself is not initialized by default. To
initialize it, you need to add 'splitapi' in the kbs-config.toml.

Signed-off-by: Salman Ahmed <[email protected]>
  • Loading branch information
salmanyam committed Dec 17, 2024
1 parent 54dd787 commit 3951960
Show file tree
Hide file tree
Showing 11 changed files with 897 additions and 1 deletion.
12 changes: 12 additions & 0 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ reqwest = { version = "0.12", default-features = false, features = [
rstest = "0.18.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.132"
serde_qs = "0.13.0"
serde_with = { version = "1.11.0", features = ["base64", "hex"] }
serial_test = "0.9.0"
sha2 = "0.10"
Expand Down
1 change: 1 addition & 0 deletions kbs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ scc = "2"
semver = "1.0.16"
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_qs.workspace = true
strum.workspace = true
thiserror.workspace = true
time = { version = "0.3.23", features = ["std"] }
Expand Down
5 changes: 5 additions & 0 deletions kbs/config/kbs-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ insecure_api = true
name = "resource"
type = "LocalFs"
dir_path = "/opt/confidential-containers/kbs/repository"

[[plugins]]
name = "splitapi"
type = "CertManager"
plugin_dir = "/opt/confidential-containers/kbs/plugin/splitapi"
2 changes: 2 additions & 0 deletions kbs/src/plugins/implementations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

pub mod splitapi;
pub mod resource;
pub mod sample;

pub use splitapi::{SplitAPI, SplitAPIConfig};
pub use resource::{RepositoryConfig, ResourceStorage};
pub use sample::{Sample, SampleConfig};
77 changes: 77 additions & 0 deletions kbs/src/plugins/implementations/splitapi/backend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2024 by IBM Corporation
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{Context, Result};
use std::{ffi::OsString, sync::Arc};
use serde::Deserialize;

use super::manager;


pub const PLUGIN_NAME: &str = "splitapi";


/// Services supported by the SplitAPI plugin
#[async_trait::async_trait]
pub trait SplitAPIBackend: Send + Sync {
/// Generate and obtain the credential for API Proxy server
async fn get_server_credential(&self, params: &SandboxParams) -> Result<Vec<u8>>;
}

pub struct SplitAPI {
pub backend: Arc<dyn SplitAPIBackend>,
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(tag = "type")]
pub enum SplitAPIConfig {
CertManager(manager::SplitAPIRepoDesc),
}

impl Default for SplitAPIConfig {
fn default() -> Self {
Self::CertManager(manager::SplitAPIRepoDesc::default())
}
}

impl TryFrom<SplitAPIConfig> for SplitAPI {
type Error = anyhow::Error;

fn try_from(config: SplitAPIConfig) -> anyhow::Result<Self> {
match config {
SplitAPIConfig::CertManager(desc) => {
let backend = manager::CertManager::new(&desc)
.context("Failed to initialize Resource Storage")?;
Ok(Self {
backend: Arc::new(backend),
})
}
}
}
}

/// Parameters taken by the "splitapi" plugin to store the certificates
/// generated for the sandbox by combining the IP address, sandbox name,
/// sandbox ID to create an unique directory for the sandbox
#[derive(Debug, PartialEq, serde::Deserialize)]
pub struct SandboxParams {
pub id: String,
pub ip: String,
pub name: String,
}

impl From<&SandboxParams> for Vec<OsString> {
fn from(params: &SandboxParams) -> Self {
let mut v: Vec<OsString> = Vec::new();

v.push("-id".into());
v.push((&params.id).into());
v.push("-name".into());
v.push((&params.name).into());
v.push("-ip".into());
v.push((&params.ip.to_string()).into());

v
}
}
Loading

0 comments on commit 3951960

Please sign in to comment.