Skip to content

Commit 159c0c1

Browse files
committed
keylimeclt: Fix requests for API version 3.0
Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
1 parent ca13b3b commit 159c0c1

File tree

6 files changed

+538
-160
lines changed

6 files changed

+538
-160
lines changed

keylimectl/src/client/agent.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ impl AgentClient {
653653
/// }
654654
/// # }
655655
/// ```
656+
#[allow(dead_code)] // Will be used when agent model detection is enabled
656657
pub fn is_pull_model(&self) -> bool {
657658
if self.api_version == UNKNOWN_API_VERSION {
658659
// Default to pull model for unknown versions to be safe

keylimectl/src/client/verifier.rs

Lines changed: 281 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,63 @@ impl VerifierClient {
584584
) -> Result<Option<Value>, KeylimectlError> {
585585
debug!("Getting agent {agent_uuid} from verifier");
586586

587+
// Try API v3.0+ first, fallback to v2.x if not implemented
588+
if self.api_version.parse::<f32>().unwrap_or(2.0) >= 3.0 {
589+
match self.get_agent_v3(agent_uuid).await {
590+
Ok(result) => return Ok(result),
591+
Err(KeylimectlError::Api { status: 404, .. }) => {
592+
debug!("V3.0 get agent endpoint not implemented, falling back to v2.x");
593+
// Continue to v2.x fallback below
594+
}
595+
Err(e) => return Err(e),
596+
}
597+
}
598+
599+
// V2.x endpoint (or fallback from v3.0)
600+
let url = format!(
601+
"{}/v2.1/agents/{}", // Use v2.1 as stable legacy version
602+
self.base.base_url, agent_uuid
603+
);
604+
605+
let response = self
606+
.base
607+
.client
608+
.get_request(Method::GET, &url)
609+
.send()
610+
.await
611+
.with_context(|| {
612+
"Failed to send get agent request to verifier".to_string()
613+
})?;
614+
615+
match response.status() {
616+
StatusCode::OK => {
617+
let json_response: Value = self
618+
.base
619+
.handle_response(response)
620+
.await
621+
.map_err(KeylimectlError::from)?;
622+
Ok(Some(json_response))
623+
}
624+
StatusCode::NOT_FOUND => Ok(None),
625+
_ => {
626+
let error_response: Result<Value, KeylimectlError> = self
627+
.base
628+
.handle_response(response)
629+
.await
630+
.map_err(KeylimectlError::from);
631+
match error_response {
632+
Ok(_) => Ok(None),
633+
Err(e) => Err(e),
634+
}
635+
}
636+
}
637+
}
638+
639+
/// Get agent using v3.0 API (when implemented)
640+
async fn get_agent_v3(
641+
&self,
642+
agent_uuid: &str,
643+
) -> Result<Option<Value>, KeylimectlError> {
587644
let url = format!(
588645
"{}/v{}/agents/{}",
589646
self.base.base_url, self.api_version, agent_uuid
@@ -596,7 +653,8 @@ impl VerifierClient {
596653
.send()
597654
.await
598655
.with_context(|| {
599-
"Failed to send get agent request to verifier".to_string()
656+
"Failed to send get agent request to verifier (v3.0)"
657+
.to_string()
600658
})?;
601659

602660
match response.status() {
@@ -668,6 +726,45 @@ impl VerifierClient {
668726
) -> Result<Value, KeylimectlError> {
669727
debug!("Deleting agent {agent_uuid} from verifier");
670728

729+
// Try API v3.0+ first, fallback to v2.x if not implemented
730+
if self.api_version.parse::<f32>().unwrap_or(2.0) >= 3.0 {
731+
match self.delete_agent_v3(agent_uuid).await {
732+
Ok(result) => return Ok(result),
733+
Err(KeylimectlError::Api { status: 404, .. }) => {
734+
debug!("V3.0 delete endpoint not implemented, falling back to v2.x");
735+
// Continue to v2.x fallback below
736+
}
737+
Err(e) => return Err(e),
738+
}
739+
}
740+
741+
// V2.x endpoint (or fallback from v3.0)
742+
let url = format!(
743+
"{}/v2.1/agents/{}", // Use v2.1 as stable legacy version
744+
self.base.base_url, agent_uuid
745+
);
746+
747+
let response = self
748+
.base
749+
.client
750+
.get_request(Method::DELETE, &url)
751+
.send()
752+
.await
753+
.with_context(|| {
754+
"Failed to send delete agent request to verifier".to_string()
755+
})?;
756+
757+
self.base
758+
.handle_response(response)
759+
.await
760+
.map_err(KeylimectlError::from)
761+
}
762+
763+
/// Delete agent using v3.0 API (when implemented)
764+
async fn delete_agent_v3(
765+
&self,
766+
agent_uuid: &str,
767+
) -> Result<Value, KeylimectlError> {
671768
let url = format!(
672769
"{}/v{}/agents/{}",
673770
self.base.base_url, self.api_version, agent_uuid
@@ -680,7 +777,8 @@ impl VerifierClient {
680777
.send()
681778
.await
682779
.with_context(|| {
683-
"Failed to send delete agent request to verifier".to_string()
780+
"Failed to send delete agent request to verifier (v3.0)"
781+
.to_string()
684782
})?;
685783

686784
self.base
@@ -696,6 +794,47 @@ impl VerifierClient {
696794
) -> Result<Value, KeylimectlError> {
697795
debug!("Reactivating agent {agent_uuid} on verifier");
698796

797+
// Try API v3.0+ first, fallback to v2.x if not implemented
798+
if self.api_version.parse::<f32>().unwrap_or(2.0) >= 3.0 {
799+
match self.reactivate_agent_v3(agent_uuid).await {
800+
Ok(result) => return Ok(result),
801+
Err(KeylimectlError::Api { status: 404, .. }) => {
802+
debug!("V3.0 reactivate endpoint not implemented, falling back to v2.x");
803+
// Continue to v2.x fallback below
804+
}
805+
Err(e) => return Err(e),
806+
}
807+
}
808+
809+
// V2.x endpoint (or fallback from v3.0)
810+
let url = format!(
811+
"{}/v2.1/agents/{}/reactivate", // Use v2.1 as stable legacy version
812+
self.base.base_url, agent_uuid
813+
);
814+
815+
let response = self
816+
.base
817+
.client
818+
.get_request(Method::PUT, &url)
819+
.body("")
820+
.send()
821+
.await
822+
.with_context(|| {
823+
"Failed to send reactivate agent request to verifier"
824+
.to_string()
825+
})?;
826+
827+
self.base
828+
.handle_response(response)
829+
.await
830+
.map_err(KeylimectlError::from)
831+
}
832+
833+
/// Reactivate agent using v3.0 API (when implemented)
834+
async fn reactivate_agent_v3(
835+
&self,
836+
agent_uuid: &str,
837+
) -> Result<Value, KeylimectlError> {
699838
let url = format!(
700839
"{}/v{}/agents/{}/reactivate",
701840
self.base.base_url, self.api_version, agent_uuid
@@ -709,7 +848,7 @@ impl VerifierClient {
709848
.send()
710849
.await
711850
.with_context(|| {
712-
"Failed to send reactivate agent request to verifier"
851+
"Failed to send reactivate agent request to verifier (v3.0)"
713852
.to_string()
714853
})?;
715854

@@ -781,6 +920,46 @@ impl VerifierClient {
781920
) -> Result<Value, KeylimectlError> {
782921
debug!("Listing agents on verifier");
783922

923+
// Try API v3.0+ first, fallback to v2.x if not implemented
924+
if self.api_version.parse::<f32>().unwrap_or(2.0) >= 3.0 {
925+
match self.list_agents_v3(verifier_id).await {
926+
Ok(result) => return Ok(result),
927+
Err(KeylimectlError::Api { status: 404, .. }) => {
928+
debug!("V3.0 list agents endpoint not implemented, falling back to v2.x");
929+
// Continue to v2.x fallback below
930+
}
931+
Err(e) => return Err(e),
932+
}
933+
}
934+
935+
// V2.x endpoint (or fallback from v3.0)
936+
let mut url = format!("{}/v2.1/agents/", self.base.base_url); // Use v2.1 as stable legacy version
937+
938+
if let Some(vid) = verifier_id {
939+
url.push_str(&format!("?verifier={vid}"));
940+
}
941+
942+
let response = self
943+
.base
944+
.client
945+
.get_request(Method::GET, &url)
946+
.send()
947+
.await
948+
.with_context(|| {
949+
"Failed to send list agents request to verifier".to_string()
950+
})?;
951+
952+
self.base
953+
.handle_response(response)
954+
.await
955+
.map_err(KeylimectlError::from)
956+
}
957+
958+
/// List agents using v3.0 API (when implemented)
959+
async fn list_agents_v3(
960+
&self,
961+
verifier_id: Option<&str>,
962+
) -> Result<Value, KeylimectlError> {
784963
let mut url =
785964
format!("{}/v{}/agents/", self.base.base_url, self.api_version);
786965

@@ -795,7 +974,8 @@ impl VerifierClient {
795974
.send()
796975
.await
797976
.with_context(|| {
798-
"Failed to send list agents request to verifier".to_string()
977+
"Failed to send list agents request to verifier (v3.0)"
978+
.to_string()
799979
})?;
800980

801981
self.base
@@ -870,6 +1050,49 @@ impl VerifierClient {
8701050
) -> Result<Value, KeylimectlError> {
8711051
debug!("Getting bulk agent info from verifier");
8721052

1053+
// Try API v3.0+ first, fallback to v2.x if not implemented
1054+
if self.api_version.parse::<f32>().unwrap_or(2.0) >= 3.0 {
1055+
match self.get_bulk_info_v3(verifier_id).await {
1056+
Ok(result) => return Ok(result),
1057+
Err(KeylimectlError::Api { status: 404, .. }) => {
1058+
debug!("V3.0 bulk info endpoint not implemented, falling back to v2.x");
1059+
// Continue to v2.x fallback below
1060+
}
1061+
Err(e) => return Err(e),
1062+
}
1063+
}
1064+
1065+
// V2.x endpoint (or fallback from v3.0)
1066+
let mut url = format!(
1067+
"{}/v2.1/agents/?bulk=true", // Use v2.1 as stable legacy version
1068+
self.base.base_url
1069+
);
1070+
1071+
if let Some(vid) = verifier_id {
1072+
url.push_str(&format!("&verifier={vid}"));
1073+
}
1074+
1075+
let response = self
1076+
.base
1077+
.client
1078+
.get_request(Method::GET, &url)
1079+
.send()
1080+
.await
1081+
.with_context(|| {
1082+
"Failed to send bulk info request to verifier".to_string()
1083+
})?;
1084+
1085+
self.base
1086+
.handle_response(response)
1087+
.await
1088+
.map_err(KeylimectlError::from)
1089+
}
1090+
1091+
/// Get bulk info using v3.0 API (when implemented)
1092+
async fn get_bulk_info_v3(
1093+
&self,
1094+
verifier_id: Option<&str>,
1095+
) -> Result<Value, KeylimectlError> {
8731096
let mut url = format!(
8741097
"{}/v{}/agents/?bulk=true",
8751098
self.base.base_url, self.api_version
@@ -886,7 +1109,8 @@ impl VerifierClient {
8861109
.send()
8871110
.await
8881111
.with_context(|| {
889-
"Failed to send bulk info request to verifier".to_string()
1112+
"Failed to send bulk info request to verifier (v3.0)"
1113+
.to_string()
8901114
})?;
8911115

8921116
self.base
@@ -903,9 +1127,25 @@ impl VerifierClient {
9031127
) -> Result<Value, KeylimectlError> {
9041128
debug!("Adding runtime policy {policy_name} to verifier");
9051129

1130+
// Try API v3.0+ first, fallback to v2.x if not implemented
1131+
if self.api_version.parse::<f32>().unwrap_or(2.0) >= 3.0 {
1132+
match self
1133+
.add_runtime_policy_v3(policy_name, policy_data.clone())
1134+
.await
1135+
{
1136+
Ok(result) => return Ok(result),
1137+
Err(KeylimectlError::Api { status: 404, .. }) => {
1138+
debug!("V3.0 runtime policy endpoint not implemented, falling back to v2.x");
1139+
// Continue to v2.x fallback below
1140+
}
1141+
Err(e) => return Err(e),
1142+
}
1143+
}
1144+
1145+
// V2.x endpoint (or fallback from v3.0)
9061146
let url = format!(
907-
"{}/v{}/allowlists/{}",
908-
self.base.base_url, self.api_version, policy_name
1147+
"{}/v2.1/allowlists/{}", // Use v2.1 as stable legacy version
1148+
self.base.base_url, policy_name
9091149
);
9101150

9111151
let response = self
@@ -931,6 +1171,40 @@ impl VerifierClient {
9311171
.map_err(KeylimectlError::from)
9321172
}
9331173

1174+
/// Add runtime policy using v3.0 API (when implemented)
1175+
async fn add_runtime_policy_v3(
1176+
&self,
1177+
policy_name: &str,
1178+
policy_data: Value,
1179+
) -> Result<Value, KeylimectlError> {
1180+
let url = format!(
1181+
"{}/v{}/policies/ima/{}",
1182+
self.base.base_url, self.api_version, policy_name
1183+
);
1184+
1185+
let response = self
1186+
.base
1187+
.client
1188+
.get_json_request_from_struct(
1189+
Method::POST,
1190+
&url,
1191+
&policy_data,
1192+
None,
1193+
)
1194+
.map_err(KeylimectlError::Json)?
1195+
.send()
1196+
.await
1197+
.with_context(|| {
1198+
"Failed to send add runtime policy request to verifier (v3.0)"
1199+
.to_string()
1200+
})?;
1201+
1202+
self.base
1203+
.handle_response(response)
1204+
.await
1205+
.map_err(KeylimectlError::from)
1206+
}
1207+
9341208
/// Get a runtime policy
9351209
pub async fn get_runtime_policy(
9361210
&self,

0 commit comments

Comments
 (0)