|
1 |
| -use std::fmt; |
2 |
| -use std::fs; |
3 |
| -use std::ops::Deref; |
4 |
| -use std::path::Path; |
| 1 | +pub mod jwt; |
| 2 | +pub mod x509; |
5 | 3 |
|
6 |
| -type OpenSSlX509Cert = ::openssl::x509::X509; |
7 |
| - |
8 |
| -use uri::URI; |
9 |
| - |
10 |
| -error_chain!{ |
11 |
| - errors { |
12 |
| - InvalidFilePath(path: String) { |
13 |
| - description("An IO error during the parsing of an SVID") |
14 |
| - display("Unable to parse SVID: Invalid file path {}", path) |
15 |
| - } |
16 |
| - |
17 |
| - InvalidPEM { |
18 |
| - description("An error during the parsing of an SVID PEM") |
19 |
| - display("Unable to parse SVID: Not a valid PEM") |
20 |
| - } |
21 |
| - |
22 |
| - InvalidDER { |
23 |
| - description("An error during the parsing of an SVID DER") |
24 |
| - display("Unable to parse SVID: Not a valid DER") |
25 |
| - } |
26 |
| - |
27 |
| - InvalidSAN { |
28 |
| - description("An error during the validation of SVID SANs") |
29 |
| - display("Unable to parse SVID: SANs do not contain a valid SPIFFE URI") |
30 |
| - } |
31 |
| - |
32 |
| - MultipleURIFound(first: String, next: String) { |
33 |
| - description("An error during the validation of SVID certificate") |
34 |
| - display("Multiple valid SPIFFE URIs found in SVID: {} & {}", first, next) |
35 |
| - } |
36 |
| - } |
37 |
| - |
38 |
| - links { |
39 |
| - Uri(::uri::Error, ::uri::ErrorKind); |
40 |
| - } |
41 |
| - |
42 |
| - foreign_links { |
43 |
| - SSL(::openssl::error::ErrorStack); |
44 |
| - Io(::std::io::Error); |
45 |
| - } |
46 |
| -} |
47 |
| - |
48 |
| -impl<'a> From<&'a Path> for ErrorKind { |
49 |
| - fn from(path: &'a Path) -> Self { |
50 |
| - ErrorKind::InvalidFilePath(path.to_str().unwrap_or("").to_string()) |
51 |
| - } |
52 |
| -} |
| 4 | +use crate::uri::URI; |
53 | 5 |
|
54 | 6 | pub trait SVIDKind {}
|
55 | 7 |
|
56 |
| -pub type Bundle = Vec<u8>; |
57 |
| -pub type Key = Vec<u8>; |
58 |
| - |
59 |
| -pub struct X509 { |
60 |
| - cert: OpenSSlX509Cert, |
61 |
| - key: Option<Key>, |
62 |
| - bundle: Option<Bundle>, |
63 |
| -} |
64 |
| - |
65 |
| -impl X509 { |
66 |
| - pub fn new(cert: OpenSSlX509Cert, key: Option<Key>, bundle: Option<Bundle>) -> X509 { |
67 |
| - X509 { |
68 |
| - cert, |
69 |
| - key: match key { |
70 |
| - Some(k) => Some(k.to_vec()), |
71 |
| - None => None, |
72 |
| - }, |
73 |
| - bundle: match bundle { |
74 |
| - Some(b) => Some(b.to_vec()), |
75 |
| - None => None, |
76 |
| - }, |
77 |
| - } |
78 |
| - } |
79 |
| - |
80 |
| - pub fn cert(&self) -> &OpenSSlX509Cert { |
81 |
| - &self.cert |
82 |
| - } |
83 |
| - |
84 |
| - pub fn key(&self) -> Option<&Vec<u8>> { |
85 |
| - match self.key { |
86 |
| - Some(ref k) => Some(&k), |
87 |
| - None => None, |
88 |
| - } |
89 |
| - } |
90 |
| - |
91 |
| - pub fn bundle(&self) -> Option<&Vec<u8>> { |
92 |
| - match self.bundle { |
93 |
| - Some(ref b) => Some(&b), |
94 |
| - None => None, |
95 |
| - } |
96 |
| - } |
97 |
| -} |
98 |
| - |
99 |
| -impl fmt::Debug for X509 { |
100 |
| - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
101 |
| - let X509 { cert, .. } = self; |
102 |
| - write!( |
103 |
| - f, |
104 |
| - "OpenSSL X509 Certificate: {{ {:?} }}", |
105 |
| - cert.to_pem().unwrap_or_else(|_| vec![]) |
106 |
| - ) |
107 |
| - } |
108 |
| -} |
109 |
| - |
110 |
| -impl SVIDKind for X509 {} |
111 |
| - |
112 | 8 | #[derive(Debug)]
|
113 | 9 | pub struct SVID<T: SVIDKind> {
|
114 | 10 | doc: T,
|
115 | 11 | uri: URI,
|
116 | 12 | }
|
117 |
| - |
118 |
| -impl SVID<X509> { |
119 |
| - pub fn from_pem(pem: &[u8], key: Option<Key>, bundle: Option<Bundle>) -> Result<SVID<X509>> { |
120 |
| - let cert = OpenSSlX509Cert::from_pem(pem).chain_err(|| ErrorKind::InvalidPEM)?; |
121 |
| - |
122 |
| - match SVID::<X509>::parse_uri(&cert) { |
123 |
| - Ok(uri) => Ok(SVID::<X509> { |
124 |
| - doc: X509::new(cert, key, bundle), |
125 |
| - uri, |
126 |
| - }), |
127 |
| - Err(e) => Err(e.chain_err(|| ErrorKind::InvalidSAN)), |
128 |
| - } |
129 |
| - } |
130 |
| - |
131 |
| - pub fn from_path(path: &Path, key: Option<&Path>, bundle: Option<&Path>) -> Result<SVID<X509>> { |
132 |
| - let contents = fs::read(path).chain_err(|| path)?; |
133 |
| - let cert = |
134 |
| - OpenSSlX509Cert::from_pem(contents.as_slice()).chain_err(|| ErrorKind::InvalidPEM)?; |
135 |
| - |
136 |
| - let key_contents = match key { |
137 |
| - Some(path) => Some(fs::read(path).chain_err(|| path)?.to_vec()), |
138 |
| - None => None, |
139 |
| - }; |
140 |
| - let bundle_contents = match bundle { |
141 |
| - Some(path) => Some(fs::read(path).chain_err(|| path)?.to_vec()), |
142 |
| - None => None, |
143 |
| - }; |
144 |
| - |
145 |
| - match SVID::<X509>::parse_uri(&cert) { |
146 |
| - Ok(uri) => Ok(SVID::<X509> { |
147 |
| - doc: X509::new(cert, key_contents, bundle_contents), |
148 |
| - uri, |
149 |
| - }), |
150 |
| - Err(e) => Err(e.chain_err(|| ErrorKind::InvalidPEM)), |
151 |
| - } |
152 |
| - } |
153 |
| - |
154 |
| - pub fn from_der(der: &[u8], key: Option<Key>, bundle: Option<Bundle>) -> Result<SVID<X509>> { |
155 |
| - let cert = OpenSSlX509Cert::from_der(der).chain_err(|| ErrorKind::InvalidDER)?; |
156 |
| - |
157 |
| - match SVID::<X509>::parse_uri(&cert) { |
158 |
| - Ok(uri) => Ok(SVID::<X509> { |
159 |
| - doc: X509::new(cert, key, bundle), |
160 |
| - uri, |
161 |
| - }), |
162 |
| - Err(e) => Err(e.chain_err(|| ErrorKind::InvalidSAN)), |
163 |
| - } |
164 |
| - } |
165 |
| - |
166 |
| - pub fn from_x509( |
167 |
| - cert: OpenSSlX509Cert, |
168 |
| - key: Option<Key>, |
169 |
| - bundle: Option<Bundle>, |
170 |
| - ) -> Result<SVID<X509>> { |
171 |
| - match SVID::<X509>::parse_uri(&cert) { |
172 |
| - Ok(uri) => Ok(SVID::<X509> { |
173 |
| - doc: X509::new(cert, key, bundle), |
174 |
| - uri, |
175 |
| - }), |
176 |
| - Err(e) => Err(e.chain_err(|| ErrorKind::InvalidPEM)), |
177 |
| - } |
178 |
| - } |
179 |
| - |
180 |
| - pub fn uri(&self) -> &URI { |
181 |
| - let SVID::<X509> { uri, .. } = self; |
182 |
| - &uri |
183 |
| - } |
184 |
| - |
185 |
| - pub fn x509(&self) -> &X509 { |
186 |
| - let SVID::<X509> { doc, .. } = self; |
187 |
| - &doc |
188 |
| - } |
189 |
| - |
190 |
| - pub fn match_spiffe_uri(&self, uri: &str) -> Result<bool> { |
191 |
| - Ok(self.uri().to_string().eq_ignore_ascii_case(uri)) |
192 |
| - } |
193 |
| - |
194 |
| - fn parse_uri(cert: &OpenSSlX509Cert) -> Result<URI> { |
195 |
| - let sans = match cert.subject_alt_names() { |
196 |
| - Some(val) => val, |
197 |
| - None => Err(ErrorKind::InvalidSAN)?, |
198 |
| - }; |
199 |
| - |
200 |
| - let mut validated_uri: Option<URI> = None; |
201 |
| - // Only allows one valid SPIFFE uri in SAN field per SPIFFE specification - returns error if multiple found |
202 |
| - for san_entry in sans { |
203 |
| - if let Some(uri) = san_entry.uri() { |
204 |
| - if let Ok(spiffe_uri) = uri.parse::<URI>() { |
205 |
| - if validated_uri.is_some() { |
206 |
| - Err(ErrorKind::MultipleURIFound( |
207 |
| - validated_uri.unwrap().to_string(), |
208 |
| - uri.to_string(), |
209 |
| - ))?; |
210 |
| - } |
211 |
| - validated_uri = Some(spiffe_uri); |
212 |
| - } |
213 |
| - } |
214 |
| - } |
215 |
| - |
216 |
| - validated_uri.ok_or_else(|| Error::from(ErrorKind::InvalidSAN)) |
217 |
| - } |
218 |
| -} |
219 |
| - |
220 |
| -impl Deref for SVID<X509> { |
221 |
| - type Target = X509; |
222 |
| - |
223 |
| - fn deref(&self) -> &X509 { |
224 |
| - let SVID::<X509> { doc, .. } = self; |
225 |
| - &doc |
226 |
| - } |
227 |
| -} |
0 commit comments