/src/ztunnel/src/proxyfactory.rs
Line | Count | Source |
1 | | // Copyright Istio Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | use crate::config; |
16 | | use crate::identity::SecretManager; |
17 | | use crate::state::{DemandProxyState, WorkloadInfo}; |
18 | | use crate::tls; |
19 | | use std::sync::Arc; |
20 | | use tracing::error; |
21 | | |
22 | | use crate::dns; |
23 | | use crate::drain::DrainWatcher; |
24 | | |
25 | | use crate::proxy::connection_manager::ConnectionManager; |
26 | | use crate::proxy::{DefaultSocketFactory, Proxy, inbound::Inbound}; |
27 | | use crate::proxy::{Error, LocalWorkloadInformation, Metrics}; |
28 | | |
29 | | // Proxy factory creates ztunnel proxies using a socket factory. |
30 | | // this allows us to create our proxies the same way in regular mode and in inpod mode. |
31 | | pub struct ProxyFactory { |
32 | | config: Arc<config::Config>, |
33 | | state: DemandProxyState, |
34 | | cert_manager: Arc<SecretManager>, |
35 | | proxy_metrics: Arc<Metrics>, |
36 | | dns_metrics: Option<Arc<dns::Metrics>>, |
37 | | drain: DrainWatcher, |
38 | | crl_manager: Option<Arc<tls::crl::CrlManager>>, |
39 | | } |
40 | | |
41 | | impl ProxyFactory { |
42 | 0 | pub fn new( |
43 | 0 | config: Arc<config::Config>, |
44 | 0 | state: DemandProxyState, |
45 | 0 | cert_manager: Arc<SecretManager>, |
46 | 0 | proxy_metrics: Arc<Metrics>, |
47 | 0 | dns_metrics: Option<dns::Metrics>, |
48 | 0 | drain: DrainWatcher, |
49 | 0 | ) -> std::io::Result<Self> { |
50 | 0 | let dns_metrics = match dns_metrics { |
51 | 0 | Some(metrics) => Some(Arc::new(metrics)), |
52 | | None => { |
53 | 0 | if config.dns_proxy { |
54 | 0 | error!("dns proxy configured but no dns metrics provided") |
55 | 0 | } |
56 | 0 | None |
57 | | } |
58 | | }; |
59 | | |
60 | | // Initialize CRL manager if crl_path is set |
61 | 0 | let crl_manager = if let Some(crl_path) = &config.crl_path { |
62 | 0 | match tls::crl::CrlManager::new(crl_path.clone()) { |
63 | 0 | Ok(manager) => { |
64 | 0 | let manager_arc = Arc::new(manager); |
65 | | |
66 | 0 | if let Err(e) = manager_arc.start_file_watcher() { |
67 | 0 | tracing::warn!( |
68 | 0 | "crl file watcher could not be started: {}. \ |
69 | 0 | crl validation will continue with current file, but \ |
70 | 0 | crl updates will require restarting ztunnel.", |
71 | | e |
72 | | ); |
73 | 0 | } |
74 | | |
75 | 0 | Some(manager_arc) |
76 | | } |
77 | 0 | Err(e) => { |
78 | 0 | tracing::warn!( |
79 | | path = ?crl_path, |
80 | | error = %e, |
81 | 0 | "failed to initialize crl manager" |
82 | | ); |
83 | 0 | None |
84 | | } |
85 | | } |
86 | | } else { |
87 | 0 | None |
88 | | }; |
89 | | |
90 | 0 | Ok(ProxyFactory { |
91 | 0 | config, |
92 | 0 | state, |
93 | 0 | cert_manager, |
94 | 0 | proxy_metrics, |
95 | 0 | dns_metrics, |
96 | 0 | drain, |
97 | 0 | crl_manager, |
98 | 0 | }) |
99 | 0 | } |
100 | | |
101 | 0 | pub async fn new_proxies_for_dedicated( |
102 | 0 | &self, |
103 | 0 | proxy_workload_info: WorkloadInfo, |
104 | 0 | ) -> Result<ProxyResult, Error> { |
105 | 0 | let base = crate::proxy::DefaultSocketFactory(self.config.socket_config); |
106 | 0 | let factory: Arc<dyn crate::proxy::SocketFactory + Send + Sync> = |
107 | 0 | if let Some(mark) = self.config.packet_mark { |
108 | 0 | Arc::new(crate::proxy::MarkSocketFactory { inner: base, mark }) |
109 | | } else { |
110 | 0 | Arc::new(base) |
111 | | }; |
112 | 0 | self.new_proxies_from_factory(None, proxy_workload_info, factory) |
113 | 0 | .await |
114 | 0 | } |
115 | | |
116 | 0 | pub async fn new_proxies_from_factory( |
117 | 0 | &self, |
118 | 0 | proxy_drain: Option<DrainWatcher>, |
119 | 0 | proxy_workload_info: WorkloadInfo, |
120 | 0 | socket_factory: Arc<dyn crate::proxy::SocketFactory + Send + Sync>, |
121 | 0 | ) -> Result<ProxyResult, Error> { |
122 | 0 | let mut result: ProxyResult = Default::default(); |
123 | 0 | let drain = proxy_drain.unwrap_or_else(|| self.drain.clone()); |
124 | | |
125 | 0 | let mut resolver = None; |
126 | | |
127 | 0 | let local_workload_information = Arc::new(LocalWorkloadInformation::new( |
128 | 0 | Arc::new(proxy_workload_info), |
129 | 0 | self.state.clone(), |
130 | 0 | self.cert_manager.clone(), |
131 | | )); |
132 | | |
133 | | // Optionally create the DNS proxy. |
134 | 0 | if self.config.dns_proxy { |
135 | 0 | let server = dns::Server::new( |
136 | 0 | self.config.cluster_domain.clone(), |
137 | 0 | self.config.dns_proxy_addr, |
138 | 0 | self.state.clone(), |
139 | 0 | dns::forwarder_for_mode( |
140 | 0 | self.config.proxy_mode, |
141 | 0 | self.config.cluster_domain.clone(), |
142 | 0 | socket_factory.clone(), |
143 | 0 | )?, |
144 | 0 | self.dns_metrics.clone().unwrap(), |
145 | 0 | drain.clone(), |
146 | 0 | socket_factory.as_ref(), |
147 | 0 | local_workload_information.as_fetcher(), |
148 | 0 | self.config.prefered_service_namespace.clone(), |
149 | 0 | self.config.ipv6_enabled, |
150 | | ) |
151 | 0 | .await?; |
152 | 0 | resolver = Some(server.resolver()); |
153 | 0 | result.dns_proxy = Some(server); |
154 | 0 | } |
155 | | |
156 | | // Optionally create the HBONE proxy. |
157 | 0 | if self.config.proxy { |
158 | 0 | let cm = ConnectionManager::default(); |
159 | 0 | let pi = crate::proxy::ProxyInputs::new( |
160 | 0 | self.config.clone(), |
161 | 0 | cm.clone(), |
162 | 0 | self.state.clone(), |
163 | 0 | self.proxy_metrics.clone(), |
164 | 0 | socket_factory.clone(), |
165 | 0 | resolver, |
166 | 0 | local_workload_information, |
167 | | false, |
168 | 0 | self.crl_manager.clone(), |
169 | | ); |
170 | 0 | result.connection_manager = Some(cm); |
171 | 0 | result.proxy = Some(Proxy::from_inputs(pi, drain).await?); |
172 | 0 | } |
173 | | |
174 | 0 | Ok(result) |
175 | 0 | } |
176 | | |
177 | | /// Creates an inbound listener specifically for ztunnel's own internal endpoints (metrics). |
178 | | /// This allows ztunnel to act as its own workload, enforcing policies on traffic directed to itself. |
179 | | /// This is distinct from the main inbound listener which handles traffic for other workloads proxied by ztunnel. |
180 | 0 | pub async fn create_ztunnel_self_proxy_listener( |
181 | 0 | &self, |
182 | 0 | ) -> Result<Option<crate::proxy::inbound::Inbound>, Error> { |
183 | 0 | if self.config.proxy_mode != config::ProxyMode::Shared { |
184 | 0 | return Ok(None); |
185 | 0 | } |
186 | | |
187 | 0 | if let (Some(ztunnel_identity), Some(ztunnel_workload)) = |
188 | 0 | (&self.config.ztunnel_identity, &self.config.ztunnel_workload) |
189 | | { |
190 | 0 | tracing::info!( |
191 | 0 | "creating ztunnel self-proxy listener with identity: {:?}", |
192 | | ztunnel_identity |
193 | | ); |
194 | | |
195 | 0 | let local_workload_information = Arc::new(LocalWorkloadInformation::new( |
196 | 0 | Arc::new(ztunnel_workload.clone()), |
197 | 0 | self.state.clone(), |
198 | 0 | self.cert_manager.clone(), |
199 | | )); |
200 | | |
201 | 0 | let socket_factory = Arc::new(DefaultSocketFactory(self.config.socket_config)); |
202 | | |
203 | 0 | let cm = ConnectionManager::default(); |
204 | | |
205 | 0 | let pi = crate::proxy::ProxyInputs::new( |
206 | 0 | self.config.clone(), |
207 | 0 | cm.clone(), |
208 | 0 | self.state.clone(), |
209 | 0 | self.proxy_metrics.clone(), |
210 | 0 | socket_factory, |
211 | 0 | None, |
212 | 0 | local_workload_information, |
213 | | true, |
214 | 0 | self.crl_manager.clone(), |
215 | | ); |
216 | | |
217 | 0 | let inbound = Inbound::new(pi, self.drain.clone()).await?; |
218 | 0 | Ok(Some(inbound)) |
219 | | } else { |
220 | 0 | Ok(None) |
221 | | } |
222 | 0 | } |
223 | | } |
224 | | |
225 | | #[derive(Default)] |
226 | | pub struct ProxyResult { |
227 | | pub proxy: Option<Proxy>, |
228 | | pub dns_proxy: Option<dns::Server>, |
229 | | pub connection_manager: Option<ConnectionManager>, |
230 | | } |