http_security_headers/
preset.rs1use crate::config::SecurityHeaders;
6use crate::policy::*;
7use std::time::Duration;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum Preset {
20 Strict,
35
36 Balanced,
48
49 Relaxed,
60}
61
62impl Preset {
63 pub fn build(self) -> SecurityHeaders {
73 match self {
74 Self::Strict => self.build_strict(),
75 Self::Balanced => self.build_balanced(),
76 Self::Relaxed => self.build_relaxed(),
77 }
78 }
79
80 fn build_strict(self) -> SecurityHeaders {
81 let csp = ContentSecurityPolicy::new()
82 .default_src(vec!["'self'"])
83 .object_src(vec!["'none'"])
84 .base_uri(vec!["'self'"])
85 .frame_ancestors(vec!["'none'"]);
86
87 SecurityHeaders::builder()
88 .content_security_policy(csp)
89 .strict_transport_security(Duration::from_secs(31536000), true, false)
90 .x_frame_options_deny()
91 .x_content_type_options_nosniff()
92 .referrer_policy_no_referrer()
93 .cross_origin_opener_policy(CrossOriginOpenerPolicy::SameOrigin)
94 .cross_origin_embedder_policy(CrossOriginEmbedderPolicy::RequireCorp)
95 .cross_origin_resource_policy(CrossOriginResourcePolicy::SameOrigin)
96 .build()
97 .expect("strict preset should always be valid")
98 }
99
100 fn build_balanced(self) -> SecurityHeaders {
101 let csp = ContentSecurityPolicy::new()
102 .default_src(vec!["'self'"])
103 .script_src(vec!["'self'", "'unsafe-inline'"])
104 .object_src(vec!["'none'"]);
105
106 SecurityHeaders::builder()
107 .content_security_policy(csp)
108 .strict_transport_security(Duration::from_secs(31536000), true, false)
109 .x_frame_options_sameorigin()
110 .x_content_type_options_nosniff()
111 .referrer_policy_strict_origin_when_cross_origin()
112 .cross_origin_opener_policy(CrossOriginOpenerPolicy::SameOriginAllowPopups)
113 .build()
114 .expect("balanced preset should always be valid")
115 }
116
117 fn build_relaxed(self) -> SecurityHeaders {
118 SecurityHeaders::builder()
119 .strict_transport_security(Duration::from_secs(15552000), false, false) .x_frame_options_sameorigin()
121 .x_content_type_options_nosniff()
122 .referrer_policy_strict_origin_when_cross_origin()
123 .build()
124 .expect("relaxed preset should always be valid")
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_strict_preset() {
134 let headers = Preset::Strict.build();
135
136 assert!(headers.content_security_policy().is_some());
137 assert!(headers.strict_transport_security().is_some());
138 assert_eq!(headers.x_frame_options(), Some(XFrameOptions::Deny));
139 assert!(headers.x_content_type_options_enabled());
140 assert_eq!(headers.referrer_policy(), Some(ReferrerPolicy::NoReferrer));
141 assert_eq!(
142 headers.cross_origin_opener_policy(),
143 Some(CrossOriginOpenerPolicy::SameOrigin)
144 );
145 assert_eq!(
146 headers.cross_origin_embedder_policy(),
147 Some(CrossOriginEmbedderPolicy::RequireCorp)
148 );
149 assert_eq!(
150 headers.cross_origin_resource_policy(),
151 Some(CrossOriginResourcePolicy::SameOrigin)
152 );
153 }
154
155 #[test]
156 fn test_balanced_preset() {
157 let headers = Preset::Balanced.build();
158
159 assert!(headers.content_security_policy().is_some());
160 assert!(headers.strict_transport_security().is_some());
161 assert_eq!(headers.x_frame_options(), Some(XFrameOptions::SameOrigin));
162 assert!(headers.x_content_type_options_enabled());
163 assert_eq!(
164 headers.referrer_policy(),
165 Some(ReferrerPolicy::StrictOriginWhenCrossOrigin)
166 );
167 assert_eq!(
168 headers.cross_origin_opener_policy(),
169 Some(CrossOriginOpenerPolicy::SameOriginAllowPopups)
170 );
171 }
172
173 #[test]
174 fn test_relaxed_preset() {
175 let headers = Preset::Relaxed.build();
176
177 assert!(headers.content_security_policy().is_none());
178 assert!(headers.strict_transport_security().is_some());
179 assert_eq!(headers.x_frame_options(), Some(XFrameOptions::SameOrigin));
180 assert!(headers.x_content_type_options_enabled());
181 assert_eq!(
182 headers.referrer_policy(),
183 Some(ReferrerPolicy::StrictOriginWhenCrossOrigin)
184 );
185
186 let hsts = headers.strict_transport_security().unwrap();
187 assert_eq!(hsts.max_age(), Duration::from_secs(15552000)); }
189}