Skip to content

Commit

Permalink
Add c8y.registration_mode enum instead of c8y.use_basic_auth bool
Browse files Browse the repository at this point in the history
Signed-off-by: Rina Fujino <[email protected]>
  • Loading branch information
rina23q committed Oct 23, 2024
1 parent 4caf2bb commit f48924b
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod flag;
pub mod host_port;
pub mod ipaddress;
pub mod port;
pub mod registration_mode;
pub mod seconds;
pub mod templates_set;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use camino::Utf8Path;
use std::str::FromStr;
use strum_macros::Display;

#[derive(
Debug, Display, Clone, Copy, Eq, PartialEq, doku::Document, serde::Serialize, serde::Deserialize,
)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
pub enum RegistrationMode {
Certificate,
Basic,
Auto,
}

#[derive(thiserror::Error, Debug)]
#[error("Failed to parse flag: {input}. Supported values are: 'certificate', 'basic' or 'auto'")]
pub struct InvalidRegistrationMode {
input: String,
}

impl FromStr for RegistrationMode {
type Err = InvalidRegistrationMode;

fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"certificate" => Ok(RegistrationMode::Certificate),
"basic" => Ok(RegistrationMode::Basic),
"auto" => Ok(RegistrationMode::Auto),
_ => Err(InvalidRegistrationMode {
input: input.to_string(),
}),
}
}
}

pub enum AuthType {
Certificate,
Basic,
}

impl RegistrationMode {
pub fn is_basic(self, credentials_path: &Utf8Path) -> bool {
matches!(self.to_type(credentials_path), AuthType::Basic)
}

pub fn is_certificate(self, credentials_path: &Utf8Path) -> bool {
matches!(self.to_type(credentials_path), AuthType::Certificate)
}

pub fn to_type(self, credentials_path: &Utf8Path) -> AuthType {
match self {
RegistrationMode::Certificate => AuthType::Certificate,
RegistrationMode::Basic => AuthType::Basic,
RegistrationMode::Auto if credentials_path.exists() => AuthType::Basic,
RegistrationMode::Auto => AuthType::Certificate,
}
}
}
11 changes: 6 additions & 5 deletions crates/common/tedge_config/src/tedge_config_cli/tedge_config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::models::timestamp::TimeFormat;
use crate::registration_mode::RegistrationMode;
use crate::AptConfig;
use crate::AutoFlag;
use crate::AutoLogUpload;
Expand Down Expand Up @@ -379,7 +380,8 @@ impl_append_remove_for_single_value!(
SecondsOrHumanTime,
u32,
AptConfig,
MqttPayloadLimit
MqttPayloadLimit,
RegistrationMode
);

impl AppendRemoveItem for TemplatesSet {
Expand Down Expand Up @@ -470,10 +472,9 @@ define_tedge_config! {
#[doku(as = "PathBuf")]
root_cert_path: Utf8PathBuf,

// TODO: Enum or bool? If enum, what are the other items?
/// Use basic authentication (username/password) instead of device certificate based authentication
#[tedge_config(example = "true", default(value = false))]
use_basic_auth: bool,
/// The type of authentication method
#[tedge_config(example = "certificate", example = "basic", example = "auto", default(variable = RegistrationMode::Certificate))]
registration_mode: RegistrationMode,

/// The path where Cumulocity username/password are stored
#[tedge_config(note = "The value must be the path of the credentials file.")]
Expand Down
39 changes: 22 additions & 17 deletions crates/core/c8y_api/src/http_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
use tedge_config::mqtt_config::MqttConfigBuildError;
use tedge_config::registration_mode::AuthType;
use tedge_config::MultiError;
use tedge_config::TEdgeConfig;
use tedge_config::TopicPrefix;
Expand Down Expand Up @@ -189,24 +190,28 @@ impl C8yAuthRetriever {
let c8y_config = tedge_config.c8y.try_get(c8y_profile)?;
let topic_prefix = c8y_config.bridge.topic_prefix.clone();

if c8y_config.use_basic_auth {
Ok(Self::Basic {
match c8y_config
.registration_mode
.to_type(&c8y_config.credentials_path)
{
AuthType::Basic => Ok(Self::Basic {
credentials_path: c8y_config.credentials_path.clone(),
})
} else {
let mqtt_config = tedge_config
.mqtt_config()
.map_err(MqttConfigBuildError::from)?;

let topic = TopicFilter::new_unchecked(&format!("{topic_prefix}/s/dat"));
let mqtt_config = mqtt_config
.with_no_session() // Ignore any already published tokens, possibly stale.
.with_subscriptions(topic);

Ok(Self::Jwt {
mqtt_config: Box::new(mqtt_config),
topic_prefix,
})
}),
AuthType::Certificate => {
let mqtt_config = tedge_config
.mqtt_config()
.map_err(MqttConfigBuildError::from)?;

let topic = TopicFilter::new_unchecked(&format!("{topic_prefix}/s/dat"));
let mqtt_config = mqtt_config
.with_no_session() // Ignore any already published tokens, possibly stale.
.with_subscriptions(topic);

Ok(Self::Jwt {
mqtt_config: Box::new(mqtt_config),
topic_prefix,
})
}
}
}

Expand Down
20 changes: 14 additions & 6 deletions crates/core/tedge/src/cli/connect/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rumqttc::QoS::AtLeastOnce;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
use tedge_config::registration_mode::AuthType;
use tedge_config::system_services::*;
use tedge_config::TEdgeConfig;
use tedge_config::*;
Expand Down Expand Up @@ -265,11 +266,15 @@ pub fn bridge_config(
Cloud::C8y => {
let c8y_config = config.c8y.try_get(profile)?;

let (remote_username, remote_password) = if c8y_config.use_basic_auth {
let (username, password) = read_c8y_credentials(&c8y_config.credentials_path)?;
(Some(username), Some(password))
} else {
(None, None)
let (remote_username, remote_password) = match c8y_config
.registration_mode
.to_type(&c8y_config.credentials_path)
{
AuthType::Certificate => (None, None),
AuthType::Basic => {
let (username, password) = read_c8y_credentials(&c8y_config.credentials_path)?;
(Some(username), Some(password))
}
};

let params = BridgeConfigC8yParams {
Expand Down Expand Up @@ -302,7 +307,10 @@ fn check_device_status_c8y(
let c8y_config = tedge_config.c8y.try_get(c8y_profile)?;

// TODO: Use SmartREST1 to check connection
if c8y_config.use_basic_auth {
if c8y_config
.registration_mode
.is_basic(&c8y_config.credentials_path)
{
return Ok(DeviceStatus::AlreadyExists);
}

Expand Down
13 changes: 8 additions & 5 deletions crates/core/tedge_mapper/src/c8y/mapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,13 @@ impl TEdgeComponent for CumulocityMapper {
.iter()
.map(|id| Cow::Owned(format!("s/dc/{id}")));

let use_certificate = c8y_config
.registration_mode
.is_certificate(&c8y_config.credentials_path);
let cloud_topics = [
("s/dt", true),
("s/ds", true),
("s/dat", !c8y_config.use_basic_auth),
("s/dat", use_certificate),
("s/e", true),
("devicecontrol/notifications", true),
("error", true),
Expand Down Expand Up @@ -129,7 +132,7 @@ impl TEdgeComponent for CumulocityMapper {
tc.forward_from_local("alarm/alarms/create/#", local_prefix.clone(), "")?;

// JWT token
if !c8y_config.use_basic_auth {
if use_certificate {
tc.forward_from_local("s/uat", local_prefix.clone(), "")?;
}

Expand All @@ -143,16 +146,16 @@ impl TEdgeComponent for CumulocityMapper {
// https://cumulocity.com/docs/device-integration/mqtt/#mqtt-clean-session
cloud_config.set_clean_session(true);

if c8y_config.use_basic_auth {
if use_certificate {
use_key_and_cert(&mut cloud_config, &c8y_config.root_cert_path, &tedge_config)?;
} else {
let (username, password) = read_c8y_credentials(&c8y_config.credentials_path)?;
use_credentials(
&mut cloud_config,
&c8y_config.root_cert_path,
username,
password,
)?;
} else {
use_key_and_cert(&mut cloud_config, &c8y_config.root_cert_path, &tedge_config)?;
}

let main_device_xid: EntityExternalId =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Custom Setup
${DEVICE_SN}= Setup skip_bootstrap=${True}
Execute Command test -f ./bootstrap.sh && ./bootstrap.sh --no-connect || true
Execute Command tedge config set mqtt.bridge.built_in ${use_builtin_bridge}
Execute Command tedge config set c8y.use_basic_auth true
Execute Command tedge config set c8y.registration_mode basic

Set Suite Variable $DEVICE_SN

Expand Down

0 comments on commit f48924b

Please sign in to comment.