From d593026b5168a9876f52c9a42b44106638f6b406 Mon Sep 17 00:00:00 2001 From: xuraoqing Date: Sat, 12 Oct 2024 14:30:44 +0800 Subject: [PATCH 1/2] agent support https to access attestation service --- .../attestation-agent/agent/src/lib.rs | 45 ++++++++++++++++--- .../attestation-agent/agent/src/main.rs | 31 +++++++++---- .../attestation-service/service/src/main.rs | 12 ++--- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/service/attestation/attestation-agent/agent/src/lib.rs b/service/attestation/attestation-agent/agent/src/lib.rs index f1c4510..673e71d 100644 --- a/service/attestation/attestation-agent/agent/src/lib.rs +++ b/service/attestation/attestation-agent/agent/src/lib.rs @@ -17,6 +17,7 @@ use anyhow::{Result, bail, anyhow}; use log; +use reqwest::Client; use serde::{Serialize, Deserialize}; use async_trait::async_trait; use std::fs::File; @@ -159,8 +160,8 @@ impl AttestationAgentAPIs for AttestationAgent { } #[derive(Clone, Debug, Serialize, Deserialize)] -struct AAConfig { - svr_url: String, // Attestation Service url +pub struct AAConfig { + pub svr_url: String, // Attestation Service url token_cfg: TokenVerifyConfig, } @@ -191,8 +192,10 @@ impl TryFrom<&Path> for AAConfig { #[derive(Debug)] pub struct AttestationAgent { - config: AAConfig, + pub config: AAConfig, as_client_sessions: SessionMap, + pub cert_root: String, + pub access_as_protocol: String, } #[allow(dead_code)] @@ -222,9 +225,32 @@ impl AttestationAgent { Ok(AttestationAgent { config, as_client_sessions, + access_as_protocol: String::from("http"), + cert_root: String::from("") }) } + fn create_client(protocol:String, cert:Option, cookie_store:bool) -> Result { + let client:Client; + if protocol == "https" { + if cert == None { + return Err(anyhow!("https need root certificate")); + } + let cert = reqwest::Certificate::from_pem(cert.unwrap().as_bytes())?; + client = reqwest::Client::builder() + .cookie_store(cookie_store) + .add_root_certificate(cert) + .build()?; + } else if protocol == "http" { + client = reqwest::Client::builder() + .cookie_store(cookie_store) + .build()?; + } else { + return Err(anyhow!("unknown {}", protocol)); + } + Ok(client) + } + #[cfg(not(feature = "no_as"))] async fn verify_evidence_by_as(&self, challenge: &[u8], @@ -239,7 +265,10 @@ impl AttestationAgent { }); let mut map = HeaderMap::new(); map.insert("Content-Type", HeaderValue::from_static("application/json")); - let mut client = reqwest::Client::new(); + let mut client = Self::create_client(self.access_as_protocol.clone(), + Some(self.cert_root.clone()), + true)?; + if !self.as_client_sessions.session_map.is_empty() { let session = self.as_client_sessions .session_map @@ -298,11 +327,13 @@ impl AttestationAgent { rand::thread_rng().fill_bytes(&mut nonce); Ok(base64_url::encode(&nonce)) } + async fn get_challenge_from_as(&self) -> Result { let challenge_endpoint = format!("{}/challenge", self.config.svr_url); - let client = reqwest::Client::builder() - .cookie_store(true) - .build()?; + let client = Self::create_client(self.access_as_protocol.clone(), + Some(self.cert_root.clone()), + true)?; + let res = client .get(challenge_endpoint) .header("Content-Type", "application/json") diff --git a/service/attestation/attestation-agent/agent/src/main.rs b/service/attestation/attestation-agent/agent/src/main.rs index 62a4b4d..bab7e0b 100644 --- a/service/attestation/attestation-agent/agent/src/main.rs +++ b/service/attestation/attestation-agent/agent/src/main.rs @@ -16,19 +16,21 @@ use restapi::{get_challenge, get_evidence, verify_evidence, get_token, verify_to use anyhow::Result; use env_logger; use actix_web::{web, App, HttpServer, HttpResponse}; -use std::{net::{SocketAddr, IpAddr, Ipv4Addr}, sync::Arc}; +use std::{sync::Arc}; use tokio::sync::RwLock; use clap::{Parser, command, arg}; -const DEFAULT_SOCKETADDR: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081); +const DEFAULT_SOCKETADDR: &str = "127.0.0.1:8081"; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Cli { /// Socket address to listen on - #[arg(short, long, default_value_t = DEFAULT_SOCKETADDR)] - socketaddr: SocketAddr, - + #[arg(short, long, default_value_t = DEFAULT_SOCKETADDR.to_string())] + socketaddr: String, + /// Socket address connect to + #[arg(short = 'u', long, default_value_t = String::from(""))] + serverurl: String, /// Load `AAConfig` from a configuration file like: /// { /// "svr_url": "http://127.0.0.1:8080", @@ -39,6 +41,13 @@ struct Cli { /// } #[arg(short, long, default_value_t = DEFAULT_AACONFIG_FILE.to_string())] config: String, + + #[arg(short = 'p', long = "protocol", default_value_t = String::from("http"))] + protocol: String, + + /// root certificate to verify peer + #[arg(short = 't', long = "cert_root", default_value_t = String::from(""))] + cert_root: String } #[actix_web::main] @@ -46,8 +55,14 @@ async fn main() -> Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); let cli = Cli::parse(); - let server = AttestationAgent::new(Some(cli.config)).unwrap(); - + let mut server = AttestationAgent::new(Some(cli.config)).unwrap(); + server.access_as_protocol = cli.protocol; + if server.access_as_protocol == "https" { + server.cert_root = std::fs::read_to_string(cli.cert_root)?; + } + if cli.serverurl != "" { + server.config.svr_url = server.access_as_protocol.clone() + "://" + &cli.serverurl.clone(); + } let service = web::Data::new(Arc::new(RwLock::new(server))); HttpServer::new(move || { App::new() @@ -59,7 +74,7 @@ async fn main() -> Result<()> { .service(verify_token) .default_service(web::to(|| HttpResponse::NotFound())) }) - .bind((cli.socketaddr.ip().to_string(), cli.socketaddr.port()))? + .bind(cli.socketaddr)? .run() .await?; diff --git a/service/attestation/attestation-service/service/src/main.rs b/service/attestation/attestation-service/service/src/main.rs index e7b2217..dfd3b7a 100644 --- a/service/attestation/attestation-service/service/src/main.rs +++ b/service/attestation/attestation-service/service/src/main.rs @@ -21,19 +21,19 @@ use anyhow::Result; use env_logger; use actix_web::{web, App, HttpServer}; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; -use std::{net::{SocketAddr, IpAddr, Ipv4Addr}, sync::Arc}; +use std::{sync::Arc}; use tokio::sync::RwLock; use clap::{Parser, command, arg}; const DEFAULT_ASCONFIG_FILE: &str = "/etc/attestation/attestation-service/attestation-service.conf"; -const DEFAULT_SOCKETADDR: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +const DEFAULT_SOCKETADDR: &str = "localhost:8080"; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Cli { /// Socket address to listen on - #[arg(short, long, default_value_t = DEFAULT_SOCKETADDR)] - socketaddr: SocketAddr, + #[arg(short, long, default_value_t = DEFAULT_SOCKETADDR.to_string())] + socketaddr: String, /// Attestation Service config file // Load `ASConfig` from a configuration file like: @@ -95,11 +95,11 @@ async fn main() -> Result<()> { let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; builder.set_private_key_file(cli.https_key, SslFiletype::PEM)?; builder.set_certificate_chain_file(cli.https_cert)?; - http_server.bind_openssl((cli.socketaddr.ip().to_string(), cli.socketaddr.port()), builder)? + http_server.bind_openssl(cli.socketaddr, builder)? .run() .await?; } else if cli.protocol == "http" { - http_server.bind((cli.socketaddr.ip().to_string(), cli.socketaddr.port()))? + http_server.bind(cli.socketaddr)? .run() .await?; } else { -- Gitee From d3329fd43ef6c60d4de9f39797c38ef742e0aa76 Mon Sep 17 00:00:00 2001 From: xuraoqing Date: Sat, 12 Oct 2024 11:49:47 +0800 Subject: [PATCH 2/2] update Readme --- service/attestation/README.md | 148 ++++++++++++------ .../attestation/attestation-service/README.md | 16 +- 2 files changed, 109 insertions(+), 55 deletions(-) diff --git a/service/attestation/README.md b/service/attestation/README.md index b6c19d8..32bfd42 100644 --- a/service/attestation/README.md +++ b/service/attestation/README.md @@ -8,38 +8,34 @@ This project provides attestation service and attestation agent for common attes Note: The roles relying party, attester and verifier is defined in [RFC9334 RATS](https://datatracker.ietf.org/doc/html/rfc9334#name-architectural-overview). # Quick Start - -## Dependencies +## Prepare +### Install attester depends SDK - OS: openEuler 24.09 - Repo ``` vim /etc/yum.repos.d/openEuler.repo [everything] name=everything -baseurl=http://121.36.84.172/dailybuild/EBS-openEuler-24.09/openeuler-2024-09-03-08-34-41/everything/aarch64/ +baseurl=https://repo.openeuler.org/openEuler-24.09/everything/aarch64/ enabled=1 gpgcheck=0 -``` - -## Build -### Build AA -``` -cd secGear/service/attestation/attestation-agent -cargo build --features virtcca-attester +yum install virtCCA_sdk-devel ``` -### Build AS -``` -cd secGear/service/attestation/attestation-service -cargo build +### Generate self-signed certificate and private key ``` +openssl genrsa -out private.pem 2048 +openssl req -new -key private.pem -out server.csr +openssl x509 -req -in server.csr -out as_cert.pem -signkey private.pem -days 3650 +mkdir -p /etc/attestation/attestation-service/token +cp private.pem /etc/attestation/attestation-service/token -## Run AS, AA and aa-test Demo -### AS -#### Config AS -- Generate as config file +// as_cert.pem will be deployed into AA config directory, AA use it to verify token +``` + +### Generate AS Config File ``` mkdir -p /etc/attestation/attestation-service/ vim /etc/attestation.bak/attestation-service/attestation-service.conf @@ -53,30 +49,48 @@ vim /etc/attestation.bak/attestation-service/attestation-service.conf } } ``` -- Generate test private key and self-signed certificate + +### Generate AA Config File +``` +mkdir -p /etc/attestation/attestation-agent/ +// svr_url: url to access attestation service +// cert: token signature certificate +// iss: token issuer name +vim /etc/attestation/attestation-agent/attestation-agent.conf +{ + "svr_url": "http://127.0.0.1:8080", + "token_cfg": { + "cert": "/etc/attestation/attestation-agent/as_cert.pem", + "iss": "oeas" + } +} ``` -openssl genrsa -out private.pem 2048 -openssl req -new -key private.pem -out server.csr -openssl x509 -req -in server.csr -out as_cert.pem -signkey private.pem -days 3650 -mkdir -p /etc/attestation/attestation-service/token -cp private.pem /etc/attestation/attestation-service/token +### Download Huawei root cert chain to verify virtCCA evidence -// as_cert.pem will be deployed into AA config directory +[Root Cert](https://download.huawei.com/dl/download.do?actionFlag=download&nid=PKI1000000002&partNo=3001&mid=SUP_PKI)
+[Sub Cert](https://download.huawei.com/dl/download.do?actionFlag=download&nid=PKI1000000040&partNo=3001&mid=SUP_PKI) +``` +mkdir -p /etc/attestation/attestation-service/verifier/virtcca +// copy Root Cert and Sub Cert to the above directory ``` -- Download Huawei root cert chain to verify virtCCA evidence - - [Root Cert](https://download.huawei.com/dl/download.do?actionFlag=download&nid=PKI1000000002&partNo=3001&mid=SUP_PKI) +## Build - [Sub Cert](https://download.huawei.com/dl/download.do?actionFlag=download&nid=PKI1000000040&partNo=3001&mid=SUP_PKI) +### Build AA +``` +cd secGear/service/attestation/attestation-agent +cargo build --features virtcca-attester ``` -mkdir -p /etc/attestation/attestation-service/verifier/virtcca -// upload root cert and sub cert to the above directory +### Build AS +``` +cd secGear/service/attestation/attestation-service +cargo build ``` -#### Run AS +## Run AS, AA and Demo(aa-test)Use HTTP +### Run AS ``` cd secGear/service/attestation/attestation-service ./target/debug/attestation-service @@ -97,33 +111,65 @@ virtcca reference (such as rim:7d2e49c8d29f18b748e658e7243ecf26bc292e5fee93f72af curl -H "Content-Type:application/json" -X POST -d '{"refs":"{\"vcca.cvm.rim\":\"7d2e49c8d29f18b748e658e7243ecf26bc292e5fee93f72af11ad9da9810142a\"}"}' http://127.0.0.1:8080/reference ``` -### AA +### Run AA -#### Install attester depends SDK +#### Run AA ``` -yum install virtCCA_sdk-devel +cd secGear/service/attestation/attestation-agent +./target/debug/attestation-agent ``` -#### Config AA + +### Run AA demo ``` -mkdir -p /etc/attestation/attestation-agent/ -// svr_url为attestation service的ip和端口,需要根据实际部署网络修改配置 -// cert 为attestation service的公钥证书,本demo为在attestation service端手动生成的自签名公钥证书 -// iss 为attestation service签发token时的签发者名称 -vim /etc/attestation/attestation-agent/attestation-agent.conf -{ - "svr_url": "http://127.0.0.1:8080", - "token_cfg": { - "cert": "/etc/attestation/attestation-agent/as_cert.pem", - "iss": "oeas" - } -} +cd secGear/service/attestation/attestation-agent +./target/debug/aa-test ``` -#### Run AA + +## Run AS, AA and Demo(aa-test)Use HTTPS +### Run AS +- generate self-signed certificate ``` -cd secGear/service/attestation/attestation-agent -./target/debug/attestation-agent +openssl genrsa -out key.pem 2048 +openssl req -subj "/C=CN/ST=ST/L=CITY/O=Company/CN=server.com" -new -key key.pem -out cert.csr +openssl x509 -req -extfile /etc/pki/tls/openssl.cnf -extensions v3_req -in cert.csr -out cert.pem -signkey key.pem -days 365 +``` + +- config hosts +``` +vim /etc/hosts +127.0.0.1 server.com +``` + +- start service +``` +cd secGear/service/attestation/attestation-service +./target/debug/attestation-service -p https -t cert.pem -k key.pem 2>&1 & +// you can specified listen port +./target/debug/attestation-service -p https -t cert.pem -k key.pem -s server.com:8080 2>&1 & ``` +- Config default policy +``` +cp secGear/service/attestation/attestation-service/policy/src/opa/default_vcca.rego /etc/attestation/attestation-service/policy +``` + +- Config virtcca reference + +virtcca reference (such as rim:7d2e49c8d29f18b748e658e7243ecf26bc292e5fee93f72af11ad9da9810142a ) is generated by [rim_ref tools](https://gitee.com/openeuler/virtCCA_sdk/tree/master/attestation/rim_ref) +``` +curl -k -H "Content-Type:application/json" -X POST -d '{"refs":"{\"vcca.cvm.rim\":\"7d2e49c8d29f18b748e658e7243ecf26bc292e5fee93f72af11ad9da9810142a\"}"}' https://server.com:8080/reference +``` + +### Run AA + +``` +cd secGear/service/attestation/attestation-agent +./target/debug/attestation-agent -p https -t cert.pem 2>&1 & + +// you can use -u specified destination which AA connect to , -s specified port which AA listen at +./target/debug/attestation-agent -p https -t cert.pem -s server.com:8081 -u server.com:8080 2>&1 & + +``` ### Run AA demo ``` cd secGear/service/attestation/attestation-agent diff --git a/service/attestation/attestation-service/README.md b/service/attestation/attestation-service/README.md index 1431ae1..af33f25 100644 --- a/service/attestation/attestation-service/README.md +++ b/service/attestation/attestation-service/README.md @@ -3,11 +3,19 @@ The Attestation Service verifies hardware TEE evidence. The first phase aims to support Kunpeng Trustzone, virtCCA and QingTian Enclave. In the future, it will support ARM CCA, Intel TDX, Hygon CSV etc. # Quick Start -## Start Attestation Service +## Start Attestation Service quickly +update repository source config ``` -config yum repository, find here: https://repo.openeuler.org/ -run service in current host like: +vim /etc/yum.repos.d/openEuler.repo +[everything] +name=everything +baseurl=https://repo.openeuler.org/openEuler-24.09/everything/aarch64/ +enabled=1 +gpgcheck=0 + +//run service in current host like this, initialize environment automaticly ./as_startup.sh -or in docker and specified interface:port: + +//or in docker and specified ip:port ./as_startup.sh -t docker -l 127.0.0.1:8080 ``` -- Gitee