From 6ad50657a57f9226755d1927912d27a1c549f722 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Wed, 3 Jul 2024 22:19:56 +0200 Subject: [PATCH] Automatically download certificate on Python device --- .../src/server/devices_api/mgmt_controller.rs | 26 +++++++++++++++++-- central_backend/src/server/servers.rs | 4 +++ python_device/src/api.py | 13 ++++++++++ python_device/src/main.py | 9 +++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/central_backend/src/server/devices_api/mgmt_controller.rs b/central_backend/src/server/devices_api/mgmt_controller.rs index f29092a..6848f60 100644 --- a/central_backend/src/server/devices_api/mgmt_controller.rs +++ b/central_backend/src/server/devices_api/mgmt_controller.rs @@ -1,3 +1,4 @@ +use crate::app_config::AppConfig; use crate::devices::device::{DeviceId, DeviceInfo}; use crate::energy::energy_actor; use crate::server::custom_error::HttpResult; @@ -73,7 +74,7 @@ pub async fn enroll(req: web::Json, actor: WebEnergyActor) -> Htt } #[derive(serde::Deserialize)] -pub struct EnrollmentStatusQuery { +pub struct ReqWithDevID { id: DeviceId, } @@ -87,7 +88,7 @@ enum EnrollmentDeviceStatus { /// Check device enrollment status pub async fn enrollment_status( - query: web::Query, + query: web::Query, actor: WebEnergyActor, ) -> HttpResult { let dev = actor @@ -102,3 +103,24 @@ pub async fn enrollment_status( Ok(HttpResponse::Ok().json(status)) } + +/// Get device certificate +pub async fn get_certificate(query: web::Query, actor: WebEnergyActor) -> HttpResult { + let dev = actor + .send(energy_actor::GetSingleDevice(query.id.clone())) + .await?; + + let dev = match dev { + Some(d) if d.validated => d, + _ => { + log::error!("Device attempted to retrieve an unavailable certificate!"); + return Ok(HttpResponse::UnprocessableEntity().json("Certificate not available yet!")); + } + }; + + let cert = std::fs::read(AppConfig::get().device_cert_path(&dev.id))?; + + Ok(HttpResponse::Ok() + .content_type("application/x-pem-file") + .body(cert)) +} diff --git a/central_backend/src/server/servers.rs b/central_backend/src/server/servers.rs index 515e3c0..e272246 100644 --- a/central_backend/src/server/servers.rs +++ b/central_backend/src/server/servers.rs @@ -160,6 +160,10 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()> "/devices_api/mgmt/enrollment_status", web::get().to(mgmt_controller::enrollment_status), ) + .route( + "/devices_api/mgmt/get_certificate", + web::get().to(mgmt_controller::get_certificate), + ) }) .bind_openssl(&AppConfig::get().listen_address, builder)? .run() diff --git a/python_device/src/api.py b/python_device/src/api.py index 80e6356..1baa642 100644 --- a/python_device/src/api.py +++ b/python_device/src/api.py @@ -56,3 +56,16 @@ def enroll_device(csr: str): if res.status_code < 200 or res.status_code > 299: print(res.text) raise Exception(f"Enrollment failed with status {res.status_code}") + +def device_certificate() -> str: + """ + Retrieve device certificate + """ + res = requests.get( + f"{args.secure_origin}/devices_api/mgmt/get_certificate?id={args.dev_id}", + verify=args.root_ca_path, + ) + if res.status_code < 200 or res.status_code > 299: + print(res.text) + raise Exception(f"Failed to check enrollment with status {res.status_code}") + return res.text diff --git a/python_device/src/main.py b/python_device/src/main.py index 0edf9e7..cfcb53a 100644 --- a/python_device/src/main.py +++ b/python_device/src/main.py @@ -72,3 +72,12 @@ if status == "Pending": exit(0) print("Device is successfully enrolled!") + +print("Check device certificate") +if not os.path.isfile(args.dev_crt_path): + print("Retrieve certificate...") + cert = api.device_certificate() + with open(args.dev_crt_path, "w") as f: + f.write(cert) + +print("Done. ready to operate.") \ No newline at end of file