Skip to content
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
19 changes: 8 additions & 11 deletions attestation-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[features]
default = ["restful-bin", "rvps-grpc", "rvps-builtin"]
default = [ "restful-bin", "rvps-grpc" ]
all-verifier = [ "verifier/all-verifier" ]
tdx-verifier = [ "verifier/tdx-verifier" ]
sgx-verifier = [ "verifier/sgx-verifier" ]
Expand All @@ -15,24 +15,21 @@ csv-verifier = [ "verifier/csv-verifier" ]
cca-verifier = [ "verifier/cca-verifier" ]
se-verifier = [ "verifier/se-verifier" ]

# Only for testing and CI
rvps-builtin = [ "reference-value-provider-service" ]

rvps-grpc = [ "prost", "tonic" ]
rvps-grpc = ["prost", "tonic"]

# For building gRPC CoCo-AS binary
grpc-bin = [ "clap", "env_logger", "prost", "tonic" ]
grpc-bin = ["clap", "env_logger", "prost", "tonic"]

# For restful CoCo-AS binary
restful-bin = [ "actix-web/openssl", "clap", "env_logger", "thiserror" ]
restful-bin = ["actix-web/openssl", "clap", "env_logger"]

[[bin]]
name = "grpc-as"
required-features = [ "grpc-bin" ]
required-features = ["grpc-bin"]

[[bin]]
name = "restful-as"
required-features = [ "restful-bin" ]
required-features = ["restful-bin"]

[dependencies]
actix-web = { workspace = true, optional = true }
Expand All @@ -50,7 +47,7 @@ log.workspace = true
openssl = "0.10.55"
prost = { workspace = true, optional = true }
rand = "0.8.5"
reference-value-provider-service = { path = "../rvps", optional = true }
reference-value-provider-service.path = "../rvps"
regorus.workspace = true
rsa = { version = "0.9.2", features = ["sha2"] }
serde.workspace = true
Expand All @@ -60,7 +57,7 @@ sha2.workspace = true
shadow-rs.workspace = true
strum.workspace = true
time = { version = "0.3.23", features = ["std"] }
thiserror = { workspace = true, optional = true }
thiserror.workspace = true
tokio.workspace = true
tonic = { workspace = true, optional = true }
uuid = { version = "1.1.2", features = ["v4"] }
Expand Down
14 changes: 1 addition & 13 deletions attestation-service/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,8 @@ VERIFIER ?= all-verifier

RVPS_GRPC := true

# TODO: Remove `RVPS_BUILTIN`
# when https://github.com/confidential-containers/trustee/pull/553 gets merged
# Here we also declare another variable `RVPS_FEATURES1` because a blank will
# be added when doing '+=' operation in Makefile
RVPS_BUILTIN := true

ifeq ($(RVPS_GRPC), true)
RVPS_FEATURES1 := rvps-grpc
endif

ifeq ($(RVPS_BUILTIN), true)
RVPS_FEATURES := $(RVPS_FEATURES1),rvps-builtin
else
RVPS_FEATURES := $(RVPS_FEATURES1)
RVPS_FEATURES := rvps-grpc
endif

ifdef DEBUG
Expand Down
4 changes: 2 additions & 2 deletions attestation-service/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"work_dir": "/var/lib/attestation-service/",
"policy_engine": "opa",
"rvps_config": {
"store_type": "LocalFs",
"remote_addr": ""
"type": "BuiltIn",
"store_type": "LocalFs"
},
"attestation_token_broker": "Simple",
"attestation_token_config": {
Expand Down
145 changes: 145 additions & 0 deletions attestation-service/docs/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# CoCo AS Configuration File

The Confidential Containers KBS properties can be configured through a
JSON-formatted configuration file.

## Configurable Properties

The following sections list the CoCo AS properties which can be set through the
configuration file.

### Global Properties

The following properties can be set globally, i.e. not under any configuration
section:

| Property | Type | Description | Required | Default |
|----------------------------|-----------------------------|-----------------------------------------------------|----------|---------|
| `work_dir` | String | The location for Attestation Service to store data. | False | Firstly try to read from ENV `AS_WORK_DIR`. If not any, use `/opt/confidential-containers/attestation-service` |
| `policy_engine` | String | Policy engine type. Valid values: `opa` | False | `opa` |
| `rvps_config` | [RVPSConfiguration][2] | RVPS configuration | False | - |
| `attestation_token_broker` | String | Type of the attestation result token broker. Valid values: `Simple` | False | `Simple` |
| `attestation_token_config` | [AttestationTokenConfig][1] | Attestation result token configuration. | False | - |

[1]: #attestationtokenconfig
[2]: #rvps-configuration

#### AttestationTokenConfig

| Property | Type | Description | Required | Default |
|----------------|-------------------------|------------------------------------------------------|----------|---------|
| `duration_min` | Integer | Duration of the attestation result token in minutes. | No | `5` |
| `issuer_name` | String | Issure name of the attestation result token. | No |`CoCo-Attestation-Service`|
| `signer` | [TokenSignerConfig][1] | Signing material of the attestation result token. | No | None |

[1]: #tokensignerconfig

#### TokenSignerConfig

This section is **optional**. When omitted, a new RSA key pair is generated and used.

| Property | Type | Description | Required | Default |
|----------------|---------|----------------------------------------------------------|----------|---------|
| `key_path` | String | RSA Key Pair file (PEM format) path. | Yes | - |
| `cert_url` | String | RSA Public Key certificate chain (PEM format) URL. | No | - |
| `cert_path` | String | RSA Public Key certificate chain (PEM format) file path. | No | - |

#### RVPS Configuration

| Property | Type | Description | Required | Default |
|----------------|-------------------------|------------------------------------------------------|----------|---------|
| `type` | String | It can be either `BuiltIn` (Built-In RVPS) or `GrpcRemote` (connect to a remote gRPC RVPS) | No | `BuiltIn` |

##### BuiltIn RVPS

If `type` is set to `BuiltIn`, the following extra properties can be set

| Property | Type | Description | Required | Default |
|----------------|-------------------------|-----------------------------------------------------------------------|----------|----------|
| `store_type` | String | The underlying storage type of RVPS. (`LocalFs` or `LocalJson`) | No | `LocalFs`|
| `store_config` | JSON Map | The optional configurations to the underlying storage. | No | Null |

Different `store_type` will have different `store_config` items.

For `LocalFs`, the following properties can be set

| Property | Type | Description | Required | Default |
|----------------|-------------------------|----------------------------------------------------------|----------|----------|
| `file_path` | String | The path to the directory storing reference values | No | `/opt/confidential-containers/attestation-service/reference_values`|

For `LocalJson`, the following properties can be set

| Property | Type | Description | Required | Default |
|----------------|-------------------------|----------------------------------------------------------|----------|----------|
| `file_path` | String | The path to the file that storing reference values | No | `/opt/confidential-containers/attestation-service/reference_values.json`|

##### Remote RVPS

If `type` is set to `GrpcRemote`, the following extra properties can be set

| Property | Type | Description | Required | Default |
|----------------|-------------------------|-----------------------------------------|----------|------------------|
| `address` | String | Remote address of the RVPS server | No | `127.0.0.1:50003`|


## Configuration Examples

Running with a built-in RVPS:

```json
{
"work_dir": "/var/lib/attestation-service/",
"policy_engine": "opa",
"rvps_config": {
"type": "BuiltIn",
"store_type": "LocalFs",
"store_config": {
"file_path": "/var/lib/attestation-service/reference-values"
}
},
"attestation_token_broker": "Simple",
"attestation_token_config": {
"duration_min": 5
}
}
```

Running with a remote RVPS:

```json
{
"work_dir": "/var/lib/attestation-service/",
"policy_engine": "opa",
"rvps_config": {
"type": "GrpcRemote",
"address": "127.0.0.1:50003"
},
"attestation_token_broker": "Simple",
"attestation_token_config": {
"duration_min": 5
}
}
```

Configurations for token signer

```json
{
"work_dir": "/var/lib/attestation-service/",
"policy_engine": "opa",
"rvps_config": {
"type": "GrpcRemote",
"address": "127.0.0.1:50003"
},
"attestation_token_broker": "Simple",
"attestation_token_config": {
"duration_min": 5,
"issuer_name": "some-body",
"signer": {
"key_path": "/etc/coco-as/signer.key",
"cert_url": "https://example.io/coco-as-certchain",
"cert_path": "/etc/coco-as/signer.pub"
}
}
}
```
2 changes: 2 additions & 0 deletions attestation-service/docs/grpc-as.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ Then a response will be returned

The value is a base64 encoded JWT. The body of the JWT is showed in the [example.token.json](./example.token.json).

More configuration items please refer to the [document](./config.md).

## Advanced Topic

### Building from Source
Expand Down
3 changes: 3 additions & 0 deletions attestation-service/docs/restful-as.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJjdXN0b21pemVkX2NsYWltcyI6eyJ0ZXN0X2tleSI

The value is a base64 encoded JWT. The body of the JWT is showed in the [example.token.json](./example.token.json).


More configuration items please refer to the [document](./config.md).

## Advanced Topics

### Building from Source
Expand Down
21 changes: 14 additions & 7 deletions attestation-service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ const DEFAULT_WORK_DIR: &str = "/opt/confidential-containers/attestation-service
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct Config {
/// The location for Attestation Service to store data.
#[serde(default = "default_work_dir")]
pub work_dir: PathBuf,

/// Policy Engine type.
#[serde(default = "default_policy_engine")]
pub policy_engine: String,

/// Configurations for RVPS.
Expand All @@ -26,13 +28,22 @@ pub struct Config {
///
/// Possible values:
/// * `Simple`
#[serde(default)]
pub attestation_token_broker: AttestationTokenBrokerType,

/// The Attestation Result Token Broker Config
#[serde(default)]
pub attestation_token_config: AttestationTokenConfig,
}

fn default_work_dir() -> PathBuf {
PathBuf::from(std::env::var(AS_WORK_DIR).unwrap_or_else(|_| DEFAULT_WORK_DIR.to_string()))
}

fn default_policy_engine() -> String {
"opa".to_string()
}

#[derive(Error, Debug)]
pub enum ConfigError {
#[error("io error: {0}")]
Expand All @@ -48,15 +59,11 @@ pub enum ConfigError {
impl Default for Config {
// Construct a default instance of `Config`
fn default() -> Config {
let work_dir = PathBuf::from(
std::env::var(AS_WORK_DIR).unwrap_or_else(|_| DEFAULT_WORK_DIR.to_string()),
);

Config {
work_dir,
policy_engine: "opa".to_string(),
work_dir: default_work_dir(),
policy_engine: default_policy_engine(),
rvps_config: RvpsConfig::default(),
attestation_token_broker: AttestationTokenBrokerType::Simple,
attestation_token_broker: AttestationTokenBrokerType::default(),
attestation_token_config: AttestationTokenConfig::default(),
}
}
Expand Down
6 changes: 4 additions & 2 deletions attestation-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//!
//! # Features
//! - `rvps-grpc`: The AS will connect a remote RVPS.
//! - `rvps-builtin`: The AS will integrate RVPS functionalities itself.

pub mod config;
pub mod policy_engine;
Expand Down Expand Up @@ -273,7 +272,10 @@ impl AttestationService {

/// Registry a new reference value
pub async fn register_reference_value(&mut self, message: &str) -> Result<()> {
self.rvps.verify_and_extract(message).await
self.rvps
.verify_and_extract(message)
.await
.context("register reference value")
}

pub async fn generate_supplemental_challenge(
Expand Down
3 changes: 1 addition & 2 deletions attestation-service/src/rvps/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::RvpsApi;
use anyhow::*;
use super::{Result, RvpsApi};
use async_trait::async_trait;
use core::result::Result::Ok;
use reference_value_provider_service::{Config, Core};
Expand Down
32 changes: 26 additions & 6 deletions attestation-service/src/rvps/grpc.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,45 @@
use crate::rvps::RvpsError;
use anyhow::{Context, Result};
use serde::Deserialize;
use thiserror::Error;
use tokio::sync::Mutex;

use self::rvps_api::{
reference_value_provider_service_client::ReferenceValueProviderServiceClient,
ReferenceValueQueryRequest, ReferenceValueRegisterRequest,
};

use super::RvpsApi;
use super::{Result, RvpsApi};

pub mod rvps_api {
tonic::include_proto!("reference");
}

#[derive(Deserialize, Clone, Debug, PartialEq)]
pub struct RvpsRemoteConfig {
/// Address of remote RVPS. If this field is given, a remote RVPS will be connected to.
/// If this field is not given, a built-in RVPS will be used.
#[serde(default = "default_address")]
pub address: String,
}

fn default_address() -> String {
"127.0.0.1:50003".into()
}

#[derive(Error, Debug)]
pub enum GrpcRvpsError {
#[error("Returned status: {0}")]
Status(#[from] tonic::Status),

#[error("tonic transport error: {0}")]
TonicTransport(#[from] tonic::transport::Error),
}

pub struct Agent {
client: Mutex<ReferenceValueProviderServiceClient<tonic::transport::Channel>>,
}

impl Agent {
pub async fn new(addr: &str) -> Result<Self, RvpsError> {
pub async fn new(addr: &str) -> Result<Self> {
Ok(Self {
client: Mutex::new(
ReferenceValueProviderServiceClient::connect(addr.to_string()).await?,
Expand All @@ -37,8 +58,7 @@ impl RvpsApi for Agent {
.lock()
.await
.register_reference_value(req)
.await
.context("register failed")?;
.await?;
Ok(())
}

Expand Down
Loading