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

KBS: Add aliyun KMS as repository storage backend #444

Merged
merged 2 commits into from
Jul 24, 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
402 changes: 363 additions & 39 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ config = "0.13.3"
env_logger = "0.10.0"
hex = "0.4.3"
jwt-simple = "0.11"
kbs_protocol = { git = "https://github.com/confidential-containers/guest-components.git", rev="9bd6f06a9704e01808e91abde130dffb20e632a5", default-features = false }
kbs-types = "0.6.0"
kms = { git = "https://github.com/confidential-containers/guest-components.git", rev="9bd6f06a9704e01808e91abde130dffb20e632a5", default-features = false }
jsonwebtoken = { version = "9", default-features = false }
log = "0.4.17"
prost = "0.12"
Expand All @@ -44,7 +46,7 @@ sha2 = "0.10"
shadow-rs = "0.19.0"
strum = { version = "0.25", features = ["derive"] }
thiserror = "1.0"
tokio = { version = "1.23.0", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tempfile = "3.4.0"
tonic = "0.11"
tonic-build = "0.11"
4 changes: 4 additions & 0 deletions kbs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ rustls = ["actix-web/rustls", "dep:rustls", "dep:rustls-pemfile"]
# Use openssl crypto stack for KBS
openssl = ["actix-web/openssl", "dep:openssl"]

# Use aliyun KMS as KBS backend
aliyun = ["kms/aliyun"]

[dependencies]
actix-web.workspace = true
actix-web-httpauth.workspace = true
Expand All @@ -57,6 +60,7 @@ env_logger.workspace = true
jsonwebtoken = { workspace = true, default-features = false, optional = true }
jwt-simple.workspace = true
kbs-types.workspace = true
kms = { workspace = true, default-features = false }
lazy_static = "1.4.0"
log.workspace = true
mobc = { version = "0.8.3", optional = true }
Expand Down
12 changes: 9 additions & 3 deletions kbs/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
AS_TYPE ?= coco-as
HTTPS_CRYPTO ?= rustls
POLICY_ENGINE ?=
ALIYUN ?= false

ARCH := $(shell uname -m)
# Check if ARCH is supported, otehrwise return error
Expand All @@ -10,6 +11,7 @@ endif

CLI_FEATURES ?=
ATTESTER ?=
FEATURES ?=

COCO_AS_INTEGRATION_TYPE ?= builtin

Expand All @@ -21,6 +23,10 @@ else
AS_FEATURE = $(AS_TYPE)
endif

ifeq ($(ALIYUN), true)
FEATURES += aliyun
endif

ifndef CLI_FEATURES
ifdef ATTESTER
CLI_FEATURES = "sample_only,$(ATTESTER)"
Expand All @@ -33,16 +39,16 @@ build: background-check-kbs

.PHONY: background-check-kbs
background-check-kbs:
cargo build -p kbs --locked --release --no-default-features --features $(AS_FEATURE),resource,$(HTTPS_CRYPTO),$(POLICY_ENGINE)
cargo build -p kbs --locked --release --no-default-features --features $(AS_FEATURE),resource,$(HTTPS_CRYPTO),$(POLICY_ENGINE),$(FEATURES)

.PHONY: passport-issuer-kbs
passport-issuer-kbs:
cargo build -p kbs --locked --release --no-default-features --features $(AS_FEATURE),$(HTTPS_CRYPTO)
cargo build -p kbs --locked --release --no-default-features --features $(AS_FEATURE),$(HTTPS_CRYPTO),$(FEATURES)
mv ../target/release/kbs ../target/release/issuer-kbs

.PHONY: passport-resource-kbs
passport-resource-kbs:
cargo build -p kbs --locked --release --no-default-features --features $(HTTPS_CRYPTO),resource,$(POLICY_ENGINE)
cargo build -p kbs --locked --release --no-default-features --features $(HTTPS_CRYPTO),resource,$(POLICY_ENGINE),$(FEATURES)
mv ../target/release/kbs ../target/release/resource-kbs

.PHONY: cli
Expand Down
11 changes: 9 additions & 2 deletions kbs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ The Makefile supports a number of other configuration parameters.

For example,
```shell
make background-check-kbs [HTTPS_CRYPTO=?] [POLICY_ENGINE=?] [AS_TYPES=?] [COCO_AS_INTEGRATION_TYPE=?]
make background-check-kbs [HTTPS_CRYPTO=?] [POLICY_ENGINE=?] [AS_TYPES=?] [COCO_AS_INTEGRATION_TYPE=?] [ALIYUN=?]
```

The parameters
Expand All @@ -99,7 +99,7 @@ The parameters
if it is not required.
- `AS_TYPES`: The KBS supports multiple backend attestation services. `AS_TYPES` selects which verifier to use. The options are `coco-as` and `intel-trust-authority-as`.
- `COCO_AS_INTEGRATION_TYPE`: The KBS can connect to the CoCo AS in multiple ways. `COCO_AS_INTEGRATION_TYPE` can be set either to `grpc` or `builtin`. With `grpc` the KBS will make a remote connection to the AS. If you are manually building and configuring the components, you'll need to set them up so that this connection can be established. Similar to passport mode, the remote AS can be useful if secret provisioning and attestation verification are not in the same scope. With `builtin` the KBA uses the AS as a crate. This is recommended if you want to avoid the complexity of a remote connection.

- `ALIYUN`: The kbs support aliyun KMS as secret storage backend. `true` to enable building this feature. By default it is `false`.
## HTTPS Support

The KBS can use HTTPS. This requires a crypto backend.
Expand All @@ -108,6 +108,13 @@ The options are `rustls` and `openssl`. The default is `rustls`.

If you want a self-signed cert for test cases, please refer to [the document](docs/self-signed-https.md).

## Storage Backend

The KBS can use different backend storage. `LocalFs` will always be builtin.
`ALIYUN` determines whether aliyun kms support will be built. The options
are `true` or `false` (by defult). Please refer to [the document](docs/config.md#repository-configuration)
for more details.

## References

### Attestation Protocol
Expand Down
6 changes: 4 additions & 2 deletions kbs/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
FROM rust:slim as builder
ARG ARCH=x86_64
ARG HTTPS_CRYPTO=rustls
ARG ALIYUN=false

ENV DEBIAN_FRONTEND noninteractive

Expand Down Expand Up @@ -36,7 +37,8 @@ RUN if [ "${ARCH}" = "x86_64" ]; then curl -fsSL https://download.01.org/intel-s
WORKDIR /usr/src/kbs
COPY . .

RUN cargo install --locked --path kbs --bin kbs --no-default-features --features coco-as-builtin,resource,opa,${HTTPS_CRYPTO}
RUN cd kbs && make AS_FEATURE=coco-as-builtin HTTPS_CRYPTO=${HTTPS_CRYPTO} POLICY_ENGINE=opa ALIYUN=${ALIYUN} && \
make install-kbs

FROM ubuntu:22.04
ARG ARCH=x86_64
Expand All @@ -60,4 +62,4 @@ RUN apt-get update && \
apt clean all && \
rm -rf /tmp/*

COPY --from=builder /usr/local/cargo/bin/kbs /usr/local/bin/kbs
COPY --from=builder /usr/local/bin/kbs /usr/local/bin/kbs
6 changes: 4 additions & 2 deletions kbs/docker/coco-as-grpc/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
FROM rust:latest as builder
ARG ARCH=x86_64
ARG HTTPS_CRYPTO=rustls
ARG ALIYUN=false

WORKDIR /usr/src/kbs
COPY . .

RUN apt-get update && apt install -y protobuf-compiler git

# Build and Install KBS
RUN cargo install --path kbs --bin kbs --no-default-features --features coco-as-grpc,resource,opa,${HTTPS_CRYPTO}
RUN cd kbs && make AS_FEATURE=coco-as-grpc HTTPS_CRYPTO=${HTTPS_CRYPTO} POLICY_ENGINE=opa ALIYUN=${ALIYUN} && \
make install-kbs

FROM ubuntu:22.04

LABEL org.opencontainers.image.source="https://github.com/confidential-containers/trustee/kbs"

COPY --from=builder /usr/local/cargo/bin/kbs /usr/local/bin/kbs
COPY --from=builder /usr/local/bin/kbs /usr/local/bin/kbs
6 changes: 4 additions & 2 deletions kbs/docker/intel-trust-authority/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
FROM rust:latest as builder
ARG HTTPS_CRYPTO=rustls
ARG ALIYUN=false

WORKDIR /usr/src/kbs
COPY . .

RUN apt-get update && apt install -y git

# Build and Install KBS
RUN cargo install --path kbs --bin kbs --no-default-features --features intel-trust-authority-as,${HTTPS_CRYPTO},resource,opa
RUN cd kbs && make AS_FEATURE=intel-trust-authority-as HTTPS_CRYPTO=${HTTPS_CRYPTO} POLICY_ENGINE=opa ALIYUN=${ALIYUN} && \
make install-kbs

FROM ubuntu:22.04

LABEL org.opencontainers.image.source="https://github.com/confidential-containers/trustee/kbs"

RUN apt update && apt install -y ca-certificates

COPY --from=builder /usr/local/cargo/bin/kbs /usr/local/bin/kbs
COPY --from=builder /usr/local/bin/kbs /usr/local/bin/kbs
17 changes: 13 additions & 4 deletions kbs/docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,27 @@ This section is **optional**. When omitted, a default configuration is used.
Repository configuration is **specific to a repository type**. See the following sections for
type-specific properties.

>This section is available only when the `resource` feature is enabled.
>This section is available only when the `resource` feature is enabled. Only one repository is available at a time.

| Property | Type | Description | Required | Default |
|----------|--------|-------------------------------------------------------|----------|-----------|
| `type` | String | The resource repository type. Valid values: `LocalFs` | Yes | - |
| Property | Type | Description | Required | Default |
|----------|--------|-----------------------------------------------------------------|----------|-----------|
| `type` | String | The resource repository type. Valid values: `LocalFs`, `Aliyun` | Yes | `LocalFs` |

**`LocalFs` Properties**

| Property | Type | Description | Required | Default |
|------------|--------|---------------------------------|----------|-----------------------------------------------------|
| `dir_path` | String | Path to a repository directory. | No | `/opt/confidential-containers/kbs/repository` |

**`Aliyun` Properties**

| Property | Type | Description | Required | Example |
|-------------------|--------|-----------------------------------|----------|-----------------------------------------------------|
| `client_key` | String | The KMS instance's AAP client key | Yes | `{"KeyId": "KA..", "PrivateKeyData": "MIIJqwI..."}` |
| `kms_instance_id` | String | The KMS instance id | Yes | `kst-shh668f7...` |
| `password` | String | AAP client key password | Yes | `8f9989c18d27...` |
| `cert_pem` | String | CA cert for the KMS instance | Yes | `-----BEGIN CERTIFICATE----- ...` |

### Native Attestation

The following properties can be set under the `as_config` section.
Expand Down
11 changes: 10 additions & 1 deletion kbs/docs/resource_repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,13 @@ defined below:
| `file://<$(KBS_REPOSITORY_DIR)>/<repository_name>/<type>/<tag>` | `https://<kbs_address>/kbs/v0/resource/<repository_name>/<type>/<tag>` |

The KBS root file system resource path is specified in the KBS config file
as well, and the default value is `/opt/confidential-containers/kbs/repository`.
as well, and the default value is `/opt/confidential-containers/kbs/repository`.

### Aliyun KMS

[Alibaba Cloud KMS](https://www.alibabacloud.com/en/product/kms?_p_lc=1)(a.k.a Aliyun KMS)
can also work as the KBS resource storage backend.
In this mode, resources will be stored with [generic secrets](https://www.alibabacloud.com/help/en/kms/user-guide/manage-and-use-generic-secrets?spm=a2c63.p38356.0.0.dc4d24f7s0ZuW7) in a [KMS instance](https://www.alibabacloud.com/help/en/kms/user-guide/kms-overview?spm=a2c63.p38356.0.0.4aacf9e6V7IQGW).
One KBS can be configured with a specified KMS instance in `repository_config` field of KBS launch config. For config, see the [document](./config.md#repository-configuration).
These materials can be found in KMS instance's [AAP](https://www.alibabacloud.com/help/en/kms/user-guide/manage-aaps?spm=a3c0i.23458820.2359477120.1.4fd96e9bmEFST4).
When being accessed, a resource URI of `kbs:///repo/type/tag` will be translated into the generic secret with name `tag`. Hinting that `repo/type` field will be ignored.
2 changes: 1 addition & 1 deletion kbs/src/http/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub(crate) async fn get_resource(
.await
.read_secret_resource(resource_description)
.await
.map_err(|e| Error::ReadSecretFailed(e.to_string()))?;
.map_err(|e| Error::ReadSecretFailed(format!("{e:?}")))?;

let jwe = jwe(pubkey, resource_byte)?;

Expand Down
59 changes: 59 additions & 0 deletions kbs/src/resource/aliyun_kms.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2024 by Alibaba.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use super::{Repository, ResourceDesc};
use anyhow::{Context, Result};
use kms::{plugins::aliyun::AliyunKmsClient, Annotations, Getter};
use log::info;
use serde::Deserialize;

#[derive(Debug, Deserialize, Clone)]
pub struct AliyunKmsBackendConfig {
client_key: String,
kms_instance_id: String,
password: String,
cert_pem: String,
}

pub struct AliyunKmsBackend {
client: AliyunKmsClient,
}

#[async_trait::async_trait]
impl Repository for AliyunKmsBackend {
async fn read_secret_resource(&self, resource_desc: ResourceDesc) -> Result<Vec<u8>> {
info!(
"Use aliyun KMS backend. Ignore {}/{}",
resource_desc.repository_name, resource_desc.resource_type
);
let name = resource_desc.resource_tag;
let resource_bytes = self
.client
.get_secret(&name, &Annotations::default())
.await
.context("failed to get resource from aliyun KMS")?;
Ok(resource_bytes)
}

async fn write_secret_resource(
&mut self,
_resource_desc: ResourceDesc,
_data: &[u8],
) -> Result<()> {
todo!("Does not support!")
}
}

impl AliyunKmsBackend {
pub fn new(repo_desc: &AliyunKmsBackendConfig) -> Result<Self> {
let client = AliyunKmsClient::new(
&repo_desc.client_key,
&repo_desc.kms_instance_id,
&repo_desc.password,
&repo_desc.cert_pem,
)
.context("create aliyun KMS backend")?;
Ok(Self { client })
}
}
14 changes: 12 additions & 2 deletions kbs/src/resource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ use serde::Deserialize;
use std::fs;
use std::path::Path;
use std::sync::Arc;
use strum::EnumString;
use tokio::sync::RwLock;

mod local_fs;

#[cfg(feature = "aliyun")]
mod aliyun_kms;

/// Interface of a `Repository`.
#[async_trait::async_trait]
pub trait Repository {
Expand Down Expand Up @@ -46,10 +48,13 @@ impl ResourceDesc {
}
}

#[derive(Clone, Debug, Deserialize, EnumString)]
#[derive(Clone, Debug, Deserialize)]
#[serde(tag = "type")]
pub enum RepositoryConfig {
LocalFs(local_fs::LocalFsRepoDesc),

#[cfg(feature = "aliyun")]
Aliyun(aliyun_kms::AliyunKmsBackendConfig),
}

impl RepositoryConfig {
Expand All @@ -73,6 +78,11 @@ impl RepositoryConfig {
Ok(Arc::new(RwLock::new(local_fs::LocalFs::new(desc)?))
as Arc<RwLock<dyn Repository + Send + Sync>>)
}
#[cfg(feature = "aliyun")]
Self::Aliyun(config) => {
let client = aliyun_kms::AliyunKmsBackend::new(config)?;
Ok(Arc::new(RwLock::new(client)) as Arc<RwLock<dyn Repository + Send + Sync>>)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tools/kbs-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ base64.workspace = true
clap = { version = "4.0.29", features = ["derive"] }
env_logger.workspace = true
jwt-simple.workspace = true
kbs_protocol = { git = "https://github.com/confidential-containers/guest-components.git", rev="df60725afe0ba452a25a740cf460c2855442c49a", default-features = false }
kbs_protocol = { workspace = true, default-features = false }
log.workspace = true
reqwest = { workspace = true, default-features = false, features = ["cookies", "json"] }
serde = { workspace = true, features = ["derive"] }
Expand Down
Loading