openstack_sdk/api/network/v2/vpn/ipsecpolicy/
create.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//
15// WARNING: This file is automatically generated from OpenAPI schema using
16// `openstack-codegenerator`.
17
18//! Creates an IP security (IPsec) policy.
19//!
20//! The IPsec policy specifies the authentication and encryption algorithms and
21//! encapsulation mode to use for the established VPN connection.
22//!
23//! Normal response codes: 201
24//!
25//! Error response codes: 400, 401
26//!
27use derive_builder::Builder;
28use http::{HeaderMap, HeaderName, HeaderValue};
29
30use crate::api::rest_endpoint_prelude::*;
31
32use serde::Deserialize;
33use serde::Serialize;
34use std::borrow::Cow;
35
36#[derive(Debug, Deserialize, Clone, Serialize)]
37pub enum AuthAlgorithm {
38    #[serde(rename = "aes-cmac")]
39    AesCmac,
40    #[serde(rename = "aes-xcbc")]
41    AesXcbc,
42    #[serde(rename = "sha1")]
43    Sha1,
44    #[serde(rename = "sha256")]
45    Sha256,
46    #[serde(rename = "sha384")]
47    Sha384,
48    #[serde(rename = "sha512")]
49    Sha512,
50}
51
52#[derive(Debug, Deserialize, Clone, Serialize)]
53pub enum EncapsulationMode {
54    #[serde(rename = "transport")]
55    Transport,
56    #[serde(rename = "tunnel")]
57    Tunnel,
58}
59
60#[derive(Debug, Deserialize, Clone, Serialize)]
61pub enum EncryptionAlgorithm {
62    #[serde(rename = "3des")]
63    _3des,
64    #[serde(rename = "aes-128")]
65    Aes128,
66    #[serde(rename = "aes-128-ccm-12")]
67    Aes128Ccm12,
68    #[serde(rename = "aes-128-ccm-16")]
69    Aes128Ccm16,
70    #[serde(rename = "aes-128-ccm-8")]
71    Aes128Ccm8,
72    #[serde(rename = "aes-128-ctr")]
73    Aes128Ctr,
74    #[serde(rename = "aes-128-gcm-12")]
75    Aes128Gcm12,
76    #[serde(rename = "aes-128-gcm-16")]
77    Aes128Gcm16,
78    #[serde(rename = "aes-128-gcm-8")]
79    Aes128Gcm8,
80    #[serde(rename = "aes-192")]
81    Aes192,
82    #[serde(rename = "aes-192-ccm-12")]
83    Aes192Ccm12,
84    #[serde(rename = "aes-192-ccm-16")]
85    Aes192Ccm16,
86    #[serde(rename = "aes-192-ccm-8")]
87    Aes192Ccm8,
88    #[serde(rename = "aes-192-ctr")]
89    Aes192Ctr,
90    #[serde(rename = "aes-192-gcm-12")]
91    Aes192Gcm12,
92    #[serde(rename = "aes-192-gcm-16")]
93    Aes192Gcm16,
94    #[serde(rename = "aes-192-gcm-8")]
95    Aes192Gcm8,
96    #[serde(rename = "aes-256")]
97    Aes256,
98    #[serde(rename = "aes-256-ccm-12")]
99    Aes256Ccm12,
100    #[serde(rename = "aes-256-ccm-16")]
101    Aes256Ccm16,
102    #[serde(rename = "aes-256-ccm-8")]
103    Aes256Ccm8,
104    #[serde(rename = "aes-256-ctr")]
105    Aes256Ctr,
106    #[serde(rename = "aes-256-gcm-12")]
107    Aes256Gcm12,
108    #[serde(rename = "aes-256-gcm-16")]
109    Aes256Gcm16,
110    #[serde(rename = "aes-256-gcm-8")]
111    Aes256Gcm8,
112}
113
114#[derive(Debug, Deserialize, Clone, Serialize)]
115pub enum Pfs {
116    #[serde(rename = "group14")]
117    Group14,
118    #[serde(rename = "group15")]
119    Group15,
120    #[serde(rename = "group16")]
121    Group16,
122    #[serde(rename = "group17")]
123    Group17,
124    #[serde(rename = "group18")]
125    Group18,
126    #[serde(rename = "group19")]
127    Group19,
128    #[serde(rename = "group2")]
129    Group2,
130    #[serde(rename = "group20")]
131    Group20,
132    #[serde(rename = "group21")]
133    Group21,
134    #[serde(rename = "group22")]
135    Group22,
136    #[serde(rename = "group23")]
137    Group23,
138    #[serde(rename = "group24")]
139    Group24,
140    #[serde(rename = "group25")]
141    Group25,
142    #[serde(rename = "group26")]
143    Group26,
144    #[serde(rename = "group27")]
145    Group27,
146    #[serde(rename = "group28")]
147    Group28,
148    #[serde(rename = "group29")]
149    Group29,
150    #[serde(rename = "group30")]
151    Group30,
152    #[serde(rename = "group31")]
153    Group31,
154    #[serde(rename = "group5")]
155    Group5,
156}
157
158#[derive(Debug, Deserialize, Clone, Serialize)]
159pub enum TransformProtocol {
160    #[serde(rename = "ah")]
161    Ah,
162    #[serde(rename = "ah-esp")]
163    AhEsp,
164    #[serde(rename = "esp")]
165    Esp,
166}
167
168/// An `ipsecpolicy` object.
169#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
170#[builder(setter(strip_option))]
171pub struct Ipsecpolicy<'a> {
172    /// The authentication hash algorithm. Valid values are `sha1`, `sha256`,
173    /// `sha384`, `sha512`, `aes-xcbc`, `aes-cmac`. The default is `sha1`.
174    #[serde(skip_serializing_if = "Option::is_none")]
175    #[builder(default)]
176    pub(crate) auth_algorithm: Option<AuthAlgorithm>,
177
178    /// A human-readable description for the resource. Default is an empty
179    /// string.
180    #[serde(skip_serializing_if = "Option::is_none")]
181    #[builder(default, setter(into))]
182    pub(crate) description: Option<Cow<'a, str>>,
183
184    /// The encapsulation mode. A valid value is `tunnel` or `transport`.
185    /// Default is `tunnel`.
186    #[serde(skip_serializing_if = "Option::is_none")]
187    #[builder(default)]
188    pub(crate) encapsulation_mode: Option<EncapsulationMode>,
189
190    /// The encryption algorithm. A valid value is `3des`, `aes-128`,
191    /// `aes-192`, `aes-256`, `aes-128-ctr`, `aes-192-ctr`, `aes-256-ctr`.
192    /// Additional values for AES CCM and GCM modes are defined (e.g.
193    /// `aes-256-ccm-16`, `aes-256-gcm-16`) for all combinations of key length
194    /// 128, 192, 256 bits and ICV length 8, 12, 16 octets. Default is
195    /// `aes-128`.
196    #[serde(skip_serializing_if = "Option::is_none")]
197    #[builder(default)]
198    pub(crate) encryption_algorithm: Option<EncryptionAlgorithm>,
199
200    /// The lifetime of the security association. The lifetime consists of a
201    /// unit and integer value. You can omit either the unit or value portion
202    /// of the lifetime. Default unit is seconds and default value is 3600.
203    #[serde(skip_serializing_if = "Option::is_none")]
204    #[builder(default, setter(into))]
205    pub(crate) lifetime: Option<Cow<'a, str>>,
206
207    /// Human-readable name of the resource. Default is an empty string.
208    #[serde(skip_serializing_if = "Option::is_none")]
209    #[builder(default, setter(into))]
210    pub(crate) name: Option<Cow<'a, str>>,
211
212    /// Perfect forward secrecy (PFS). A valid value is `Group2`, `Group5`,
213    /// `Group14` to `Group31`. Default is `Group5`.
214    #[serde(skip_serializing_if = "Option::is_none")]
215    #[builder(default)]
216    pub(crate) pfs: Option<Pfs>,
217
218    /// The ID of the project.
219    #[serde(skip_serializing_if = "Option::is_none")]
220    #[builder(default, setter(into))]
221    pub(crate) tenant_id: Option<Cow<'a, str>>,
222
223    /// The transform protocol. A valid value is `ESP`, `AH`, or `AH- ESP`.
224    /// Default is `ESP`.
225    #[serde(skip_serializing_if = "Option::is_none")]
226    #[builder(default)]
227    pub(crate) transform_protocol: Option<TransformProtocol>,
228}
229
230#[derive(Builder, Debug, Clone)]
231#[builder(setter(strip_option))]
232pub struct Request<'a> {
233    /// An `ipsecpolicy` object.
234    #[builder(setter(into))]
235    pub(crate) ipsecpolicy: Ipsecpolicy<'a>,
236
237    #[builder(setter(name = "_headers"), default, private)]
238    _headers: Option<HeaderMap>,
239}
240impl<'a> Request<'a> {
241    /// Create a builder for the endpoint.
242    pub fn builder() -> RequestBuilder<'a> {
243        RequestBuilder::default()
244    }
245}
246
247impl<'a> RequestBuilder<'a> {
248    /// Add a single header to the Ipsecpolicy.
249    pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
250    where
251        K: Into<HeaderName>,
252        V: Into<HeaderValue>,
253    {
254        self._headers
255            .get_or_insert(None)
256            .get_or_insert_with(HeaderMap::new)
257            .insert(header_name.into(), header_value.into());
258        self
259    }
260
261    /// Add multiple headers.
262    pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
263    where
264        I: Iterator<Item = T>,
265        T: Into<(Option<HeaderName>, HeaderValue)>,
266    {
267        self._headers
268            .get_or_insert(None)
269            .get_or_insert_with(HeaderMap::new)
270            .extend(iter.map(Into::into));
271        self
272    }
273}
274
275impl RestEndpoint for Request<'_> {
276    fn method(&self) -> http::Method {
277        http::Method::POST
278    }
279
280    fn endpoint(&self) -> Cow<'static, str> {
281        "vpn/ipsecpolicies".to_string().into()
282    }
283
284    fn parameters(&self) -> QueryParams<'_> {
285        QueryParams::default()
286    }
287
288    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
289        let mut params = JsonBodyParams::default();
290
291        params.push("ipsecpolicy", serde_json::to_value(&self.ipsecpolicy)?);
292
293        params.into_body()
294    }
295
296    fn service_type(&self) -> ServiceType {
297        ServiceType::Network
298    }
299
300    fn response_key(&self) -> Option<Cow<'static, str>> {
301        Some("ipsecpolicy".into())
302    }
303
304    /// Returns headers to be set into the request
305    fn request_headers(&self) -> Option<&HeaderMap> {
306        self._headers.as_ref()
307    }
308
309    /// Returns required API version
310    fn api_version(&self) -> Option<ApiVersion> {
311        Some(ApiVersion::new(2, 0))
312    }
313}
314
315#[cfg(test)]
316mod tests {
317    use super::*;
318    #[cfg(feature = "sync")]
319    use crate::api::Query;
320    use crate::test::client::FakeOpenStackClient;
321    use crate::types::ServiceType;
322    use http::{HeaderName, HeaderValue};
323    use httpmock::MockServer;
324    use serde_json::json;
325
326    #[test]
327    fn test_service_type() {
328        assert_eq!(
329            Request::builder()
330                .ipsecpolicy(IpsecpolicyBuilder::default().build().unwrap())
331                .build()
332                .unwrap()
333                .service_type(),
334            ServiceType::Network
335        );
336    }
337
338    #[test]
339    fn test_response_key() {
340        assert_eq!(
341            Request::builder()
342                .ipsecpolicy(IpsecpolicyBuilder::default().build().unwrap())
343                .build()
344                .unwrap()
345                .response_key()
346                .unwrap(),
347            "ipsecpolicy"
348        );
349    }
350
351    #[cfg(feature = "sync")]
352    #[test]
353    fn endpoint() {
354        let server = MockServer::start();
355        let client = FakeOpenStackClient::new(server.base_url());
356        let mock = server.mock(|when, then| {
357            when.method(httpmock::Method::POST)
358                .path("/vpn/ipsecpolicies".to_string());
359
360            then.status(200)
361                .header("content-type", "application/json")
362                .json_body(json!({ "ipsecpolicy": {} }));
363        });
364
365        let endpoint = Request::builder()
366            .ipsecpolicy(IpsecpolicyBuilder::default().build().unwrap())
367            .build()
368            .unwrap();
369        let _: serde_json::Value = endpoint.query(&client).unwrap();
370        mock.assert();
371    }
372
373    #[cfg(feature = "sync")]
374    #[test]
375    fn endpoint_headers() {
376        let server = MockServer::start();
377        let client = FakeOpenStackClient::new(server.base_url());
378        let mock = server.mock(|when, then| {
379            when.method(httpmock::Method::POST)
380                .path("/vpn/ipsecpolicies".to_string())
381                .header("foo", "bar")
382                .header("not_foo", "not_bar");
383            then.status(200)
384                .header("content-type", "application/json")
385                .json_body(json!({ "ipsecpolicy": {} }));
386        });
387
388        let endpoint = Request::builder()
389            .ipsecpolicy(IpsecpolicyBuilder::default().build().unwrap())
390            .headers(
391                [(
392                    Some(HeaderName::from_static("foo")),
393                    HeaderValue::from_static("bar"),
394                )]
395                .into_iter(),
396            )
397            .header(
398                HeaderName::from_static("not_foo"),
399                HeaderValue::from_static("not_bar"),
400            )
401            .build()
402            .unwrap();
403        let _: serde_json::Value = endpoint.query(&client).unwrap();
404        mock.assert();
405    }
406}