rs_consul/acl.rs
1use std::time::Duration;
2
3use crate::ACLPolicy;
4use crate::ACLToken;
5use crate::Consul;
6use crate::CreateACLPolicyRequest;
7use crate::CreateACLTokenPayload;
8use crate::Function;
9use crate::Result;
10use crate::errors::ConsulError;
11
12use http::Method;
13use http_body_util::Empty;
14use http_body_util::Full;
15use http_body_util::combinators::BoxBody;
16
17use hyper::body::Buf;
18use hyper::body::Bytes;
19
20impl Consul {
21 /// Returns all ACL tokens.
22 ///
23 /// Fetches the list of ACL tokens from Consul’s `/v1/acl/tokens` endpoint.
24 /// Users can use these tokens to manage access control for Consul resources.
25 /// See the [Consul API docs](https://developer.hashicorp.com/consul/api-docs/acl/tokens#list-tokens) for more information.
26 ///
27 /// # Arguments:
28 /// - `&self` – the `Consul` client instance.
29 ///
30 /// # Errors:
31 /// - [`ConsulError::ResponseDeserializationFailed`] if the response JSON can’t be parsed.
32 pub async fn get_acl_tokens(&self) -> Result<Vec<ACLToken>> {
33 let uri = format!("{}/v1/acl/tokens", self.config.address);
34 let request = hyper::Request::builder().method(Method::GET).uri(uri);
35 let (body, _) = self
36 .execute_request(
37 request,
38 BoxBody::new(Empty::<Bytes>::new()),
39 Some(Duration::from_secs(5)),
40 crate::Function::GetAclTokens,
41 )
42 .await?;
43 serde_json::from_reader(body.reader()).map_err(ConsulError::ResponseDeserializationFailed)
44 }
45
46 /// Returns all ACL policies.
47 ///
48 /// Retrieves the list of ACL policies defined in Consul via the `/v1/acl/policies` endpoint.
49 /// ACL policies define sets of rules for tokens to grant or restrict permissions.
50 /// See the [Consul API docs](https://developer.hashicorp.com/consul/api-docs/acl/policies#list-policies) for more information.
51 ///
52 /// # Arguments:
53 /// - `&self` – the `Consul` client instance.
54 ///
55 /// # Errors:
56 /// - [`ConsulError::ResponseDeserializationFailed`] if the response JSON can’t be parsed.
57 pub async fn get_acl_policies(&self) -> Result<Vec<ACLPolicy>> {
58 let uri = format!("{}/v1/acl/policies", self.config.address);
59 let request = hyper::Request::builder().method(Method::GET).uri(uri);
60 let (body, _) = self
61 .execute_request(
62 request,
63 BoxBody::new(Empty::<Bytes>::new()),
64 Some(Duration::from_secs(5)),
65 crate::Function::GetACLPolicies,
66 )
67 .await?;
68 serde_json::from_reader(body.reader()).map_err(ConsulError::ResponseDeserializationFailed)
69 }
70
71 /// Delete an acl policy.
72 ///
73 /// Sends a `DELETE` to `/v1/acl/policy/:id` to delete an ACL policy in Consul.
74 ///
75 /// # Arguments:
76 /// - `&self` – the `Consul` client instance.
77 /// - `id` – the policy ID.
78 ///
79 /// # Errors:
80 /// - [`ConsulError::InvalidRequest`] if the payload fails to serialize.
81 /// - [`ConsulError::ResponseDeserializationFailed`] if the Consul response can’t be parsed.
82 pub async fn delete_acl_policy(&self, id: String) -> Result<()> {
83 let uri = format!("{}/v1/acl/policy/{}", self.config.address, id);
84 let request = hyper::Request::builder().method(Method::DELETE).uri(uri);
85 self.execute_request(
86 request,
87 BoxBody::new(Empty::<Bytes>::new()),
88 Some(Duration::from_secs(5)),
89 Function::DeleteACLPolicy,
90 )
91 .await?;
92 Ok(())
93 }
94
95 /// Creates a new ACL policy.
96 ///
97 /// Sends a `PUT` to `/v1/acl/policy` to define a new ACL policy in Consul.
98 /// ACL policies consist of rules that can be attached to tokens to control access.
99 /// See the [Consul API docs](https://developer.hashicorp.com/consul/api-docs/acl/policies#create-policy) for more information.
100 ///
101 /// # Arguments:
102 /// - `&self` – the `Consul` client instance.
103 /// - `payload` – the [`CreateACLPolicyRequest`](crate::types::CreateACLPolicyRequest) payload.
104 ///
105 /// # Errors:
106 /// - [`ConsulError::InvalidRequest`] if the payload fails to serialize.
107 /// - [`ConsulError::ResponseDeserializationFailed`] if the Consul response can’t be parsed.
108 pub async fn create_acl_policy(&self, payload: &CreateACLPolicyRequest) -> Result<ACLPolicy> {
109 let uri = format!("{}/v1/acl/policy", self.config.address);
110 let request = hyper::Request::builder().method(Method::PUT).uri(uri);
111 let payload = serde_json::to_string(payload).map_err(ConsulError::InvalidRequest)?;
112 let (resp, _) = self
113 .execute_request(
114 request,
115 BoxBody::new(Full::<Bytes>::new(Bytes::from(payload.into_bytes()))),
116 Some(Duration::from_secs(5)),
117 Function::CreateACLPolicy,
118 )
119 .await?;
120 serde_json::from_reader(resp.reader()).map_err(ConsulError::ResponseDeserializationFailed)
121 }
122
123 /// Creates a new ACL token.
124 ///
125 /// Sends a `PUT` to `/v1/acl/token` to generate a new token which can be attached to ACL policies.
126 /// Tokens grant the permissions defined by their associated policies.
127 /// See the [Consul API docs](https://developer.hashicorp.com/consul/api-docs/acl/tokens#create-token) for more information.
128 ///
129 /// # Arguments:
130 /// - `&self` – the `Consul` client instance.
131 /// - `payload` – the [`CreateACLTokenPayload`](crate::CreateACLTokenPayload) payload.
132 ///
133 /// # Errors:
134 /// - [`ConsulError::InvalidRequest`] if the payload fails to serialize.
135 /// - [`ConsulError::ResponseDeserializationFailed`] if the response JSON can’t be parsed.
136 pub async fn create_acl_token(&self, payload: &CreateACLTokenPayload) -> Result<ACLToken> {
137 let uri = format!("{}/v1/acl/token", self.config.address);
138 let request = hyper::Request::builder().method(Method::PUT).uri(uri);
139 let payload = serde_json::to_string(payload).map_err(ConsulError::InvalidRequest)?;
140 let (resp, _) = self
141 .execute_request(
142 request,
143 BoxBody::new(Full::<Bytes>::new(Bytes::from(payload.into_bytes()))),
144 Some(Duration::from_secs(5)),
145 Function::CreateACLPolicy,
146 )
147 .await?;
148 serde_json::from_reader(resp.reader()).map_err(ConsulError::ResponseDeserializationFailed)
149 }
150
151 /// Reads an ACL token.
152 ///
153 /// Fetches a single ACL token by its ID using the `/v1/acl/token/{token}` endpoint.
154 /// Useful for inspecting the token’s properties and associated policies.
155 /// See the [Consul API docs](https://developer.hashicorp.com/consul/api-docs/acl/tokens#read-token) for more information.
156 ///
157 /// # Arguments:
158 /// - `&self` – the `Consul` client instance.
159 /// - `accessor_id` – the accessor_id to read.
160 ///
161 /// # Errors:
162 /// - [`ConsulError::ResponseDeserializationFailed`] if the response JSON can’t be parsed.
163 pub async fn read_acl_token(&self, accessor_id: String) -> Result<ACLToken> {
164 let uri = format!("{}/v1/acl/token/{}", self.config.address, accessor_id);
165 let request = hyper::Request::builder().method(Method::GET).uri(uri);
166 let (resp_body, _) = self
167 .execute_request(
168 request,
169 BoxBody::new(Empty::<Bytes>::new()),
170 Some(Duration::from_secs(5)),
171 crate::Function::ReadACLToken,
172 )
173 .await?;
174 serde_json::from_reader(resp_body.reader())
175 .map_err(ConsulError::ResponseDeserializationFailed)
176 }
177
178 /// Deletes an ACL token.
179 ///
180 /// Sends a `DELETE` to `/v1/acl/token/{token}` to remove the specified ACL token.
181 /// Returns `false` if deletion failed, in which case this method returns an error.
182 /// See the [Consul API docs](https://developer.hashicorp.com/consul/api-docs/acl/tokens#delete-token) for more information.
183 ///
184 /// # Arguments:
185 /// - `&self` – the `Consul` client instance.
186 /// - `token` – the token ID to delete.
187 ///
188 /// # Errors:
189 /// - [`ConsulError::ResponseDeserializationFailed`] if the response JSON can’t be parsed.
190 /// - [`ConsulError::TokenDeleteFailed`] if Consul indicates deletion did not succeed.
191 pub async fn delete_acl_token(&self, token: String) -> Result<()> {
192 let uri = format!("{}/v1/acl/token/{}", self.config.address, token);
193 let request = hyper::Request::builder().method(Method::DELETE).uri(uri);
194 let (resp_body, _) = self
195 .execute_request(
196 request,
197 BoxBody::new(Empty::<Bytes>::new()),
198 Some(Duration::from_secs(5)),
199 crate::Function::DeleteACLToken,
200 )
201 .await?;
202 let ok: bool = serde_json::from_reader(resp_body.reader())
203 .map_err(ConsulError::ResponseDeserializationFailed)?;
204 if !ok {
205 return Err(ConsulError::TokenDeleteFailed);
206 }
207 Ok(())
208 }
209}