Skip to content

Commit 12a9ed6

Browse files
committed
introduce admin_api_ro flag to restrict operations to only r/o
In operator-based deployments, kbs-client (and in general the admin API) should not be allowed to try and modify the resources, for two reasons: 1. trustee runs in a container so the fs is r/o 2. management of such resources is by design delegated to kubernetes configmaps Therefore add admin_api_ro flags defaulting to false under the [admin] section of kbs-config.toml. Signed-off-by: Emanuele Giuseppe Esposito <[email protected]>
1 parent 93b5ac4 commit 12a9ed6

File tree

6 files changed

+43
-6
lines changed

6 files changed

+43
-6
lines changed

integration-tests/src/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl TestHarness {
206206
admin: AdminConfig {
207207
auth_public_key: None,
208208
insecure_api: true,
209+
admin_api_read_only: false,
209210
},
210211
policy_engine: PolicyEngineConfig {
211212
policy_path: kbs_policy_path,

kbs/docs/config.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,11 @@ Detailed [documentation](https://docs.trustauthority.intel.com).
204204

205205
The following properties can be set under the `[admin]` section.
206206

207-
| Property | Type | Description | Required | Default |
208-
|-------------------|---------|-------------------------------------------------------------------|----------|---------|
209-
| `auth_public_key` | String | Path to the public key used to authenticate the admin APIs | No | None |
210-
| `insecure_api` | Boolean | Whether KBS will not verify the public key when called admin APIs | No | `false` |
207+
| Property | Type | Description | Required | Default |
208+
|------------------------|---------|-------------------------------------------------------------------|----------|---------|
209+
| `auth_public_key` | String | Path to the public key used to authenticate the admin APIs | No | None |
210+
| `insecure_api` | Boolean | Whether KBS will not verify the public key when called admin APIs | No | `false` |
211+
| `admin_api_read_only` | Boolean | Limit the admin APIs to only get resources. | No | `false` |
211212

212213
### Policy Engine Configuration
213214

kbs/src/admin/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::path::PathBuf;
77
use serde::Deserialize;
88

99
pub const DEFAULT_INSECURE_API: bool = false;
10+
pub const DEFAULT_ADMIN_API_READ_ONLY: bool = false;
1011

1112
#[derive(Clone, Debug, Deserialize, PartialEq)]
1213
pub struct AdminConfig {
@@ -18,13 +19,18 @@ pub struct AdminConfig {
1819
/// WARNING: Using this option enables KBS insecure APIs such as Resource Registration without
1920
/// verifying the JWK.
2021
pub insecure_api: bool,
22+
23+
/// Whether the admin APIs should be read-only or not.
24+
/// Useful for operator-based deployments.
25+
pub admin_api_read_only: bool,
2126
}
2227

2328
impl Default for AdminConfig {
2429
fn default() -> Self {
2530
Self {
2631
auth_public_key: None,
2732
insecure_api: DEFAULT_INSECURE_API,
33+
admin_api_read_only: DEFAULT_ADMIN_API_READ_ONLY,
2834
}
2935
}
3036
}

kbs/src/admin/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub enum Error {
1919
#[error("`auth_public_key` is not set in the config file")]
2020
NoPublicKeyGiven,
2121

22+
#[error("`admin_api_read_only` limits the admin API to read-only operations (GET/HEAD)")]
23+
AdminApiReadOnly,
24+
2225
#[error("Failed to parse admin public key")]
2326
ParsePublicKey(#[from] jwt_simple::Error),
2427

kbs/src/admin/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
// SPDX-License-Identifier: Apache-2.0
44

5-
use actix_web::{http::header::Header, HttpRequest};
5+
use actix_web::{
6+
http::{header::Header, Method},
7+
HttpRequest,
8+
};
69
use actix_web_httpauth::headers::authorization::{Authorization, Bearer};
710
use config::AdminConfig;
811
use jwt_simple::{
@@ -19,12 +22,21 @@ use log::warn;
1922
#[derive(Default, Clone)]
2023
pub struct Admin {
2124
public_key: Option<Ed25519PublicKey>,
25+
admin_api_read_only: bool,
2226
}
2327

2428
impl TryFrom<AdminConfig> for Admin {
2529
type Error = Error;
2630

2731
fn try_from(value: AdminConfig) -> Result<Self> {
32+
if value.admin_api_read_only {
33+
warn!("admin API is disabled");
34+
return Ok(Self {
35+
public_key: None,
36+
admin_api_read_only: true,
37+
});
38+
}
39+
2840
if value.insecure_api {
2941
warn!("insecure admin APIs are enabled");
3042
return Ok(Admin::default());
@@ -35,12 +47,19 @@ impl TryFrom<AdminConfig> for Admin {
3547
let key = Ed25519PublicKey::from_pem(&user_public_key_pem)?;
3648
Ok(Self {
3749
public_key: Some(key),
50+
admin_api_read_only: false,
3851
})
3952
}
4053
}
4154

4255
impl Admin {
4356
pub(crate) fn validate_auth(&self, request: &HttpRequest) -> Result<()> {
57+
if self.admin_api_read_only
58+
&& (request.method() != Method::GET || request.method() != Method::HEAD)
59+
{
60+
return Err(Error::AdminApiReadOnly);
61+
}
62+
4463
let Some(public_key) = &self.public_key else {
4564
return Ok(());
4665
};

kbs/src/config.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
// SPDX-License-Identifier: Apache-2.0
44

5-
use crate::admin::config::{AdminConfig, DEFAULT_INSECURE_API};
5+
use crate::admin::config::{AdminConfig, DEFAULT_ADMIN_API_READ_ONLY, DEFAULT_INSECURE_API};
66
use crate::plugins::PluginsConfig;
77
use crate::policy_engine::PolicyEngineConfig;
88
use crate::token::AttestationTokenVerifierConfig;
@@ -83,6 +83,7 @@ impl TryFrom<&Path> for KbsConfig {
8383
fn try_from(config_path: &Path) -> Result<Self, Self::Error> {
8484
let c = Config::builder()
8585
.set_default("admin.insecure_api", DEFAULT_INSECURE_API)?
86+
.set_default("admin.admin_api_read_only", DEFAULT_ADMIN_API_READ_ONLY)?
8687
.set_default("http_server.insecure_http", DEFAULT_INSECURE_HTTP)?
8788
.set_default("http_server.sockets", vec![DEFAULT_SOCKET])?
8889
.set_default(
@@ -169,6 +170,7 @@ mod tests {
169170
admin: AdminConfig {
170171
auth_public_key: Some(PathBuf::from("/etc/kbs-admin.pub")),
171172
insecure_api: false,
173+
admin_api_read_only: false,
172174
},
173175
policy_engine: PolicyEngineConfig {
174176
policy_path: PathBuf::from("/etc/kbs-policy.rego"),
@@ -218,6 +220,7 @@ mod tests {
218220
admin: AdminConfig {
219221
auth_public_key: None,
220222
insecure_api: DEFAULT_INSECURE_API,
223+
admin_api_read_only: false,
221224
},
222225
policy_engine: PolicyEngineConfig {
223226
policy_path: DEFAULT_POLICY_PATH.into(),
@@ -255,6 +258,7 @@ mod tests {
255258
admin: AdminConfig {
256259
auth_public_key: Some(PathBuf::from("/etc/kbs-admin.pub")),
257260
insecure_api: false,
261+
admin_api_read_only: false,
258262
},
259263
policy_engine: PolicyEngineConfig {
260264
policy_path: PathBuf::from("/etc/kbs-policy.rego"),
@@ -293,6 +297,7 @@ mod tests {
293297
admin: AdminConfig {
294298
auth_public_key: Some(PathBuf::from("/opt/confidential-containers/kbs/user-keys/public.pub")),
295299
insecure_api: DEFAULT_INSECURE_API,
300+
admin_api_read_only: false,
296301
},
297302
policy_engine: PolicyEngineConfig::default(),
298303
plugins: Vec::new(),
@@ -334,6 +339,7 @@ mod tests {
334339
admin: AdminConfig {
335340
auth_public_key: Some("/kbs/kbs.pem".into()),
336341
insecure_api: DEFAULT_INSECURE_API,
342+
admin_api_read_only: false,
337343
},
338344
policy_engine: PolicyEngineConfig::default(),
339345
plugins: Vec::new(),
@@ -369,6 +375,7 @@ mod tests {
369375
admin: AdminConfig {
370376
auth_public_key: Some("/kbs/kbs.pem".into()),
371377
insecure_api: DEFAULT_INSECURE_API,
378+
admin_api_read_only: false,
372379
},
373380
policy_engine: PolicyEngineConfig::default(),
374381
plugins: Vec::new(),

0 commit comments

Comments
 (0)