mirror of https://github.com/rwf2/Rocket.git
Add 'space_helmet' contrib module.
This commit is contained in:
parent
0ac6c18deb
commit
c5167f1150
|
@ -8,6 +8,7 @@ members = [
|
|||
"core/http/",
|
||||
"contrib/lib",
|
||||
"contrib/codegen",
|
||||
"examples/space_helmet",
|
||||
"examples/cookies",
|
||||
"examples/errors",
|
||||
"examples/form_validation",
|
||||
|
|
|
@ -21,6 +21,7 @@ json = ["serde", "serde_json"]
|
|||
msgpack = ["serde", "rmp-serde"]
|
||||
tera_templates = ["tera", "templates"]
|
||||
handlebars_templates = ["handlebars", "templates"]
|
||||
space_helmet = ["time"]
|
||||
serve = []
|
||||
|
||||
# The barage of user-facing database features.
|
||||
|
@ -66,8 +67,14 @@ r2d2_cypher = { version = "0.4", optional = true }
|
|||
redis = { version = "0.9", optional = true }
|
||||
r2d2_redis = { version = "0.8", optional = true }
|
||||
|
||||
# SpaceHelmet dependencies
|
||||
time = { version = "0.1.40", optional = true }
|
||||
|
||||
[target.'cfg(debug_assertions)'.dependencies]
|
||||
notify = { version = "^4.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket_codegen = { version = "0.4.0-dev", path = "../../core/codegen" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
//! * [tera_templates](templates) - Tera Templating
|
||||
//! * [uuid](uuid) - UUID (de)serialization
|
||||
//! * [${database}_pool](databases) - Database Configuration and Pooling
|
||||
//! * [space_helmet](space_helmet)
|
||||
//!
|
||||
//! The recommend way to include features from this crate via Cargo in your
|
||||
//! project is by adding a `[dependencies.rocket_contrib]` section to your
|
||||
|
@ -49,6 +50,7 @@
|
|||
#[cfg(feature="templates")] pub mod templates;
|
||||
#[cfg(feature="uuid")] pub mod uuid;
|
||||
#[cfg(feature="databases")] pub mod databases;
|
||||
#[cfg(feature = "space_helmet")] pub mod space_helmet;
|
||||
|
||||
#[cfg(feature="databases")] extern crate rocket_contrib_codegen;
|
||||
#[cfg(feature="databases")] #[doc(hidden)] pub use rocket_contrib_codegen::*;
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use rocket::fairing::{Fairing, Info, Kind};
|
||||
use rocket::http::Header;
|
||||
use rocket::{Request, Response, Rocket};
|
||||
|
||||
use super::policy::*;
|
||||
|
||||
/// A [`Fairing`](/rocket/fairing/trait.Fairing.html)
|
||||
/// that adds HTTP headers to outgoing responses that control security features
|
||||
/// on the browser.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// `SpaceHelmet` can be used in several ways.
|
||||
///
|
||||
/// To use it with its [defaults](#method.default), create a new instance and
|
||||
/// attach it to [Rocket](/rocket/struct.Rocket.html)
|
||||
/// as shown.
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// use rocket_contrib::space_helmet::SpaceHelmet;
|
||||
///
|
||||
/// let rocket = rocket::ignite().attach(SpaceHelmet::default());
|
||||
/// ```
|
||||
///
|
||||
/// To enable an additional header, call the method for that header, with the
|
||||
/// policy for that header, before attach e.g.
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// use rocket_contrib::space_helmet::{SpaceHelmet, ReferrerPolicy};
|
||||
///
|
||||
/// let helmet = SpaceHelmet::default().referrer_policy(ReferrerPolicy::NoReferrer);
|
||||
/// let rocket = rocket::ignite().attach(helmet);
|
||||
/// ```
|
||||
///
|
||||
/// To disable a header, call the method for that header with `None` as
|
||||
/// the policy.
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// use rocket_contrib::space_helmet::SpaceHelmet;
|
||||
///
|
||||
/// let helmet = SpaceHelmet::default().no_sniff(None);
|
||||
/// let rocket = rocket::ignite().attach(helmet);
|
||||
/// ```
|
||||
///
|
||||
/// `SpaceHelmet` supports the builder pattern to configure multiple policies
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// use rocket_contrib::space_helmet::{HstsPolicy, ExpectCtPolicy, ReferrerPolicy, SpaceHelmet};
|
||||
///
|
||||
/// let helmet = SpaceHelmet::default()
|
||||
/// .hsts(HstsPolicy::default())
|
||||
/// .expect_ct(ExpectCtPolicy::default())
|
||||
/// .referrer_policy(ReferrerPolicy::default());
|
||||
///
|
||||
/// let rocket = rocket::ignite().attach(helmet);
|
||||
/// ```
|
||||
///
|
||||
/// # TLS and HSTS
|
||||
///
|
||||
/// If TLS is enabled when a [Rocket](rocket/struct.Rocket.html)
|
||||
/// is [launched](/rocket/fairing/trait.Fairing.html#method.on_launch)
|
||||
/// in a non-development environment e.g. [Staging](rocket/struct.Config.html#method.staging)
|
||||
/// or [Production](/rocket/struct.Config.html#method.production)
|
||||
/// `SpaceHelmet` enables hsts with its default policy and issue a
|
||||
/// warning.
|
||||
///
|
||||
/// To get rid of this warning, set an [hsts](#method.hsts) policy if you are using tls.
|
||||
pub struct SpaceHelmet<'a> {
|
||||
expect_ct_policy: Option<ExpectCtPolicy<'a>>,
|
||||
no_sniff_policy: Option<NoSniffPolicy>,
|
||||
xss_protect_policy: Option<XssPolicy<'a>>,
|
||||
frameguard_policy: Option<FramePolicy<'a>>,
|
||||
hsts_policy: Option<HstsPolicy>,
|
||||
force_hsts_policy: Option<HstsPolicy>,
|
||||
force_hsts: AtomicBool,
|
||||
referrer_policy: Option<ReferrerPolicy>,
|
||||
}
|
||||
|
||||
// helper for Helmet.apply
|
||||
macro_rules! try_apply_header {
|
||||
($self:ident, $response:ident, $policy_name:ident) => {
|
||||
if let Some(ref policy) = $self.$policy_name {
|
||||
if $response.set_header(policy) {
|
||||
warn_!(
|
||||
"(Space Helmet): set_header failed, found existing header \"{}\"",
|
||||
Header::from(policy).name
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a> Default for SpaceHelmet<'a> {
|
||||
/// Returns a new `SpaceHelmet` instance. See [table](/rocket_contrib/space_helmet/index.html#what-it-supports) for
|
||||
/// a description of what policies are used by default.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// use rocket_contrib::space_helmet::SpaceHelmet;
|
||||
///
|
||||
/// let helmet = SpaceHelmet::default();
|
||||
/// ```
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
expect_ct_policy: None,
|
||||
no_sniff_policy: Some(NoSniffPolicy::default()),
|
||||
frameguard_policy: Some(FramePolicy::default()),
|
||||
xss_protect_policy: Some(XssPolicy::default()),
|
||||
hsts_policy: None,
|
||||
force_hsts_policy: Some(HstsPolicy::default()),
|
||||
force_hsts: AtomicBool::new(false),
|
||||
referrer_policy: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SpaceHelmet<'a> {
|
||||
/// Same as [`SpaceHelmet::default()`].
|
||||
pub fn new() -> Self {
|
||||
SpaceHelmet::default()
|
||||
}
|
||||
|
||||
/// Sets the [X-XSS-Protection](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection)
|
||||
/// header to the given `policy` or disables it if `policy == None`.
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// use rocket::http::uri::Uri;
|
||||
/// use rocket_contrib::space_helmet::{SpaceHelmet, XssPolicy};
|
||||
///
|
||||
/// let report_uri = Uri::parse("https://www.google.com").unwrap();
|
||||
/// let helmet = SpaceHelmet::new().xss_protect(XssPolicy::EnableReport(report_uri));
|
||||
/// ```
|
||||
pub fn xss_protect<T: Into<Option<XssPolicy<'a>>>>(mut self, policy: T) -> SpaceHelmet<'a> {
|
||||
self.xss_protect_policy = policy.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [X-Content-Type-Options](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)
|
||||
/// header to `policy` or disables it if `policy == None`.
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
///
|
||||
/// use rocket_contrib::space_helmet::{SpaceHelmet, NoSniffPolicy};
|
||||
///
|
||||
/// let helmet = SpaceHelmet::new().no_sniff(NoSniffPolicy::Enable);
|
||||
/// ```
|
||||
pub fn no_sniff<T: Into<Option<NoSniffPolicy>>>(mut self, policy: T) -> SpaceHelmet<'a> {
|
||||
self.no_sniff_policy = policy.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [X-Frame-Options](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options)
|
||||
/// header to `policy`, or disables it if `policy == None`.
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
///
|
||||
/// use rocket::http::uri::Uri;
|
||||
/// use rocket_contrib::space_helmet::{SpaceHelmet, FramePolicy};
|
||||
///
|
||||
/// let allow_uri = Uri::parse("https://www.google.com").unwrap();
|
||||
/// let helmet = SpaceHelmet::new().frameguard(FramePolicy::AllowFrom(allow_uri));
|
||||
/// ```
|
||||
pub fn frameguard<T: Into<Option<FramePolicy<'a>>>>(mut self, policy: T) -> SpaceHelmet<'a> {
|
||||
self.frameguard_policy = policy.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [Strict-Transport-Security](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
|
||||
/// header to `policy`, or disables it if `policy == None`.
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket_contrib::space_helmet::{SpaceHelmet, HstsPolicy};
|
||||
///
|
||||
/// let helmet = SpaceHelmet::new().hsts(HstsPolicy::default());
|
||||
/// ```
|
||||
pub fn hsts<T: Into<Option<HstsPolicy>>>(mut self, policy: T) -> SpaceHelmet<'a> {
|
||||
self.hsts_policy = policy.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [Expect-CT](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT)
|
||||
/// header to `policy`, or disables it if `policy == None`.
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
/// # extern crate time;
|
||||
/// use rocket::http::uri::Uri;
|
||||
/// use rocket_contrib::space_helmet::{SpaceHelmet, ExpectCtPolicy};
|
||||
/// use time::Duration;
|
||||
///
|
||||
/// let report_uri = Uri::parse("https://www.google.com").unwrap();
|
||||
/// let helmet = SpaceHelmet::new()
|
||||
/// .expect_ct(ExpectCtPolicy::ReportAndEnforce(
|
||||
/// Duration::days(30), report_uri));
|
||||
/// ```
|
||||
pub fn expect_ct<T: Into<Option<ExpectCtPolicy<'a>>>>(mut self, policy: T) -> SpaceHelmet<'a> {
|
||||
self.expect_ct_policy = policy.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [Referrer-Policy](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy)
|
||||
/// header to `policy`, or disables it if `policy == None`.
|
||||
/// ```rust
|
||||
/// # extern crate rocket;
|
||||
/// # extern crate rocket_contrib;
|
||||
///
|
||||
/// use rocket_contrib::space_helmet::{ReferrerPolicy, SpaceHelmet};
|
||||
///
|
||||
/// let helmet = SpaceHelmet::new().referrer_policy(ReferrerPolicy::NoReferrer);
|
||||
/// ```
|
||||
pub fn referrer_policy<T: Into<Option<ReferrerPolicy>>>(
|
||||
mut self,
|
||||
policy: T,
|
||||
) -> SpaceHelmet<'a> {
|
||||
self.referrer_policy = policy.into();
|
||||
self
|
||||
}
|
||||
|
||||
fn apply(&self, response: &mut Response) {
|
||||
try_apply_header!(self, response, no_sniff_policy);
|
||||
try_apply_header!(self, response, xss_protect_policy);
|
||||
try_apply_header!(self, response, frameguard_policy);
|
||||
try_apply_header!(self, response, expect_ct_policy);
|
||||
try_apply_header!(self, response, referrer_policy);
|
||||
if self.hsts_policy.is_some() {
|
||||
try_apply_header!(self, response, hsts_policy);
|
||||
} else {
|
||||
if self.force_hsts.load(Ordering::Relaxed) {
|
||||
try_apply_header!(self, response, force_hsts_policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fairing for SpaceHelmet<'static> {
|
||||
fn info(&self) -> Info {
|
||||
Info {
|
||||
name: "Rocket SpaceHelmet (HTTP Security Headers)",
|
||||
kind: Kind::Response | Kind::Launch,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_response(&self, _request: &Request, response: &mut Response) {
|
||||
self.apply(response);
|
||||
}
|
||||
|
||||
fn on_launch(&self, rocket: &Rocket) {
|
||||
if rocket.config().tls_enabled()
|
||||
&& !rocket.config().environment.is_dev()
|
||||
&& !self.hsts_policy.is_some()
|
||||
{
|
||||
warn_!("(Space Helmet): deploying with TLS without enabling hsts.");
|
||||
warn_!("Enabling default HSTS policy.");
|
||||
info_!("To disable this warning, configure an HSTS policy.");
|
||||
self.force_hsts.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
//! [`SpaceHelmet`] is a [`Fairing`](/rocket/fairing/trait.Fairing.html) that
|
||||
//! turns on browsers security features by adding HTTP headers to all outgoing
|
||||
//! responses.
|
||||
//!
|
||||
//! It provides a typed interface for http security headers and takes some
|
||||
//! inspiration from [helmet](https://helmetjs.github.io/), a similar piece
|
||||
//! of middleware for [express](https://expressjs.com).
|
||||
//!
|
||||
//! ### What it supports
|
||||
//!
|
||||
//! | HTTP Header | Description | Method | Enabled by Default? |
|
||||
//! | --------------------------- | -------------------------------------- | ---------------------------------- | ------------------- |
|
||||
//! | [X-XSS-Protection] | Prevents some reflected XSS attacks. | [`SpaceHelmet::xss_protect()`] | ✔ |
|
||||
//! | [X-Content-Type-Options] | Prevents client sniffing of MIME type. | [`SpaceHelmet::no_sniff()`] | ✔ |
|
||||
//! | [X-Frame-Options] | Prevents [clickjacking]. | [`SpaceHelmet::frameguard()`] | ✔ |
|
||||
//! | [Strict-Transport-Security] | Enforces strict use of HTTPS. | [`SpaceHelmet::hsts()`] | ? |
|
||||
//! | [Expect-CT] | Enables certificate transparency. | [`SpaceHelmet::expect_ct()`] | ✗ |
|
||||
//! | [Referrer-Policy] | Enables referrer policy. | [`SpaceHelmet::referrer_policy()`] | ✗ |
|
||||
//!
|
||||
//! [X-XSS-Protection]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
|
||||
//! [X-Content-Type-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
|
||||
//! [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
||||
//! [Strict-Transport-Security]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
|
||||
//! [Expect-CT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT
|
||||
//! [Referrer-Policy]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
|
||||
//! [clickjacking]: https://en.wikipedia.org/wiki/Clickjacking
|
||||
//! _? If tls is enabled when a [Rocket](/rocket/struct.Rocket.html) is
|
||||
//! [launched()'ed](/rocket/fairing/trait.Fairing.html)
|
||||
//! in a non-development environment e.g. [Staging](/rocket/struct.Config.html#method.staging)
|
||||
//! or [Production](/rocket/struct.Config.html#method.production), `SpaceHelmet` enables hsts with its
|
||||
//! default policy and outputs a warning._
|
||||
//!
|
||||
//! ### Examples
|
||||
//!
|
||||
//! To apply the headers that are enabled by default, just create a new [`SpaceHelmet`] instance
|
||||
//! and attach before launch.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # extern crate rocket;
|
||||
//! # extern crate rocket_contrib;
|
||||
//! use rocket_contrib::space_helmet::{SpaceHelmet};
|
||||
//!
|
||||
//! let rocket = rocket::ignite().attach(SpaceHelmet::new());
|
||||
//! ```
|
||||
//!
|
||||
//! Each header can be configured individually if desired. To enable a particular
|
||||
//! header, call the method for the header on the [`SpaceHelmet`] instance. Multiple
|
||||
//! method calls can be chained in a builder pattern as illustrated below.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # extern crate rocket;
|
||||
//! # extern crate rocket_contrib;
|
||||
//! use rocket::http::uri::Uri;
|
||||
//!
|
||||
//! // Every header has a corresponding policy type.
|
||||
//! use rocket_contrib::space_helmet::{SpaceHelmet, FramePolicy, XssPolicy, HstsPolicy};
|
||||
//!
|
||||
//! let site_uri = Uri::parse("https://mysite.example.com").unwrap();
|
||||
//! let report_uri = Uri::parse("https://report.example.com").unwrap();
|
||||
//! let helmet = SpaceHelmet::new()
|
||||
//! .hsts(HstsPolicy::default()) // each policy has a default.
|
||||
//! .no_sniff(None) // setting policy to None disables the header.
|
||||
//! .frameguard(FramePolicy::AllowFrom(site_uri))
|
||||
//! .xss_protect(XssPolicy::EnableReport(report_uri));
|
||||
//! ```
|
||||
//!
|
||||
//! #### Still have questions?
|
||||
//!
|
||||
//! * _What policy should I choose?_ Check out the links in the table
|
||||
//! above for individual header documentation. The [helmetjs](https://helmetjs.github.io/) doc's
|
||||
//! are also a good resource, and owasp has a collection of [references] on these headers.
|
||||
//!
|
||||
//! [references]: https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers
|
||||
//!
|
||||
//! * _Where I can I read more about using fairings?_ Check out the
|
||||
//! [fairing](https://rocket.rs/guide/fairings/) section of the rocket guide.
|
||||
//!
|
||||
//! * _Do I only need those headers `SpaceHelmet` enables by default?_ Maybe, the other headers
|
||||
//! can protect against many important vulnerabilities. Please consult their documentation and
|
||||
//! other resources to find out if they are needed for your project.
|
||||
|
||||
extern crate time;
|
||||
|
||||
mod helmet;
|
||||
mod policy;
|
||||
|
||||
pub use self::helmet::*;
|
||||
pub use self::policy::*;
|
|
@ -0,0 +1,302 @@
|
|||
use std::borrow::Cow;
|
||||
use rocket::http::uri::Uri;
|
||||
use rocket::http::Header;
|
||||
|
||||
use super::time::Duration;
|
||||
|
||||
/// The [Referrer-Policy] header tells the browser if should send all or part of URL of the current
|
||||
/// page to the next site the user navigates to via the [Referer] header. This can be important
|
||||
/// for security as the URL itself might expose sensitive data, such as a hidden file path or
|
||||
/// personal identifier.
|
||||
///
|
||||
/// [Referrer-Policy]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
|
||||
/// [Referer]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer
|
||||
pub enum ReferrerPolicy {
|
||||
/// Omits the `Referer` header (_SpaceHelmet default_).
|
||||
NoReferrer,
|
||||
|
||||
/// Omits the `Referer` header on connection downgrade i.e. following HTTP link from HTTPS site
|
||||
/// (_Browser default_).
|
||||
NoReferrerWhenDowngrade,
|
||||
|
||||
/// Only send the origin of part of the URL, e.g. the origin of https://foo.com/bob.html is
|
||||
/// https://foo.com
|
||||
Origin,
|
||||
|
||||
/// Send full URL for same-origin requests, only send origin part when replying
|
||||
/// to [cross-origin] requests.
|
||||
///
|
||||
/// [cross-origin]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
OriginWhenCrossOrigin,
|
||||
|
||||
/// Send full URL for same-origin requests only.
|
||||
SameOrigin,
|
||||
|
||||
/// Only send origin part of URL, only send if protocol security level remains the same e.g.
|
||||
/// HTTPS to HTTPS.
|
||||
StrictOrigin,
|
||||
|
||||
/// Send full URL for same-origin requests. For cross-origin requests, only send origin
|
||||
/// part of URL if protocl security level remains the same e.g. HTTPS to HTTPS.
|
||||
StrictOriginWhenCrossOrigin,
|
||||
|
||||
/// Send full URL for same-origin or cross-origin requests. _This will leak the full
|
||||
/// URL of TLS protected resources to insecure origins. Use with caution._
|
||||
UnsafeUrl,
|
||||
}
|
||||
|
||||
/// Defaults to [`ReferrerPolicy::NoReferrer`]. Tells the browser Omit the `Referer` header.
|
||||
impl Default for ReferrerPolicy {
|
||||
fn default() -> ReferrerPolicy {
|
||||
ReferrerPolicy::NoReferrer
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<&'a ReferrerPolicy> for Header<'b> {
|
||||
fn from(policy: &ReferrerPolicy) -> Header<'b> {
|
||||
let policy_string = match policy {
|
||||
ReferrerPolicy::NoReferrer => "no-referrer",
|
||||
ReferrerPolicy::NoReferrerWhenDowngrade => "no-referrer-when-downgrade",
|
||||
ReferrerPolicy::Origin => "origin",
|
||||
ReferrerPolicy::OriginWhenCrossOrigin => "origin-when-cross-origin",
|
||||
ReferrerPolicy::SameOrigin => "same-origin",
|
||||
ReferrerPolicy::StrictOrigin => "strict-origin",
|
||||
ReferrerPolicy::StrictOriginWhenCrossOrigin => {
|
||||
"strict-origin-when-cross-origin"
|
||||
}
|
||||
ReferrerPolicy::UnsafeUrl => "unsafe-url",
|
||||
};
|
||||
|
||||
Header::new("Referrer-Policy", policy_string)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The [Expect-CT] header tells browser to enable [Certificate Transparency] checking, which
|
||||
/// can detect and prevent the misuse of the site's certificate. Read all [`ExpectCtPolicy`]
|
||||
/// documentation before use.
|
||||
///
|
||||
/// [Certificate Transparency]
|
||||
/// solves a variety of problems with public TLS/SSL certificate management and is valuable
|
||||
/// measure if your standing up a public website. If your [getting started] with certificate
|
||||
/// transparency, be sure that your [site is in compliance][getting started] before you turn on
|
||||
/// enforcement with [`ExpectCtPolicy::Enforce`] or [`ExpectCtPolicy::ReportAndEnforce`]
|
||||
/// otherwise the browser will stop talking to your site until you bring it into compliance
|
||||
/// or [`Duration`] time elapses. _You have been warned_.
|
||||
///
|
||||
///
|
||||
///
|
||||
/// [Expect-CT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT
|
||||
/// [Certificate Transparency]: http://www.certificate-transparency.org/what-is-ct
|
||||
/// [getting started]: http://www.certificate-transparency.org/getting-started
|
||||
pub enum ExpectCtPolicy<'a> {
|
||||
/// Tells browser to enforce certificate compliance for [`Duration`] seconds.
|
||||
/// Check if your site is in compliance before turning on enforcement.
|
||||
/// (_SpaceHelmet_ default).
|
||||
Enforce(Duration),
|
||||
|
||||
/// Tells browser to report compliance violations certificate transparency for [`Duration`]
|
||||
/// seconds. Doesn't provide any protection but is a good way make sure
|
||||
/// things are working correctly before turning on enforcement in production.
|
||||
Report(Duration, Uri<'a>),
|
||||
|
||||
/// Enforces compliance and supports notification to if there has been a violation for
|
||||
/// [`Duration`].
|
||||
ReportAndEnforce(Duration, Uri<'a>),
|
||||
}
|
||||
|
||||
/// Defaults to [`ExpectCtPolicy::Enforce(Duration::days(30))`], enforce CT
|
||||
/// compliance, see [draft] standard for more.
|
||||
///
|
||||
/// [draft]: https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct-03#page-15
|
||||
impl<'a> Default for ExpectCtPolicy<'a> {
|
||||
fn default() -> ExpectCtPolicy<'a> {
|
||||
ExpectCtPolicy::Enforce(Duration::days(30))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<&'a ExpectCtPolicy<'a>> for Header<'b> {
|
||||
fn from(policy: &ExpectCtPolicy<'a>) -> Header<'b> {
|
||||
let policy_string = match policy {
|
||||
ExpectCtPolicy::Enforce(max_age) => format!("max-age={}, enforce", max_age.num_seconds()),
|
||||
ExpectCtPolicy::Report(max_age, url) => {
|
||||
format!("max-age={}, report-uri=\"{}\"", max_age.num_seconds(), url)
|
||||
}
|
||||
ExpectCtPolicy::ReportAndEnforce(max_age, url) => {
|
||||
format!("max-age={}, enforce, report-uri=\"{}\"", max_age.num_seconds(), url)
|
||||
}
|
||||
};
|
||||
|
||||
Header::new("Expect-CT", policy_string)
|
||||
}
|
||||
}
|
||||
|
||||
/// The [X-Content-Type-Options] header can tell the browser to turn off [mime sniffing](
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#MIME_sniffing) which
|
||||
/// can prevent certain [attacks].
|
||||
///
|
||||
/// [X-Content-Type-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
|
||||
/// [attacks]: https://helmetjs.github.io/docs/dont-sniff-mimetype/
|
||||
pub enum NoSniffPolicy {
|
||||
|
||||
///Turns off mime sniffing.
|
||||
Enable,
|
||||
}
|
||||
|
||||
/// Defaults to [`NoSniffPolicy::Enable`], turns off mime sniffing.
|
||||
impl Default for NoSniffPolicy {
|
||||
fn default() -> NoSniffPolicy {
|
||||
NoSniffPolicy::Enable
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<&'a NoSniffPolicy> for Header<'b> {
|
||||
fn from(_policy: &NoSniffPolicy) -> Header<'b> {
|
||||
Header::new("X-Content-Type-Options", "nosniff")
|
||||
}
|
||||
}
|
||||
|
||||
/// The HTTP [Strict-Transport-Security] (HSTS) header tells the browser that the site should only
|
||||
/// be accessed using HTTPS instead of HTTP. HSTS prevents a variety of downgrading attacks and
|
||||
/// should always be used when TLS is enabled. `SpaceHelmet` will turn HSTS on and
|
||||
/// issue a warning if you enable TLS without enabling HSTS in [Staging ] or [Production].
|
||||
/// Read full [`HstsPolicy`] documentation before you configure this.
|
||||
///
|
||||
/// HSTS is important for HTTPS security, however, incorrectly configured HSTS can lead to problems as
|
||||
/// you are disallowing access to non-HTTPS enabled parts of your site. [Yelp engineering] has good
|
||||
/// discussion of potential challenges that can arise, and how to roll this out in a large scale setting.
|
||||
/// So, if you use TLS, use HSTS, just roll it out with care.
|
||||
///
|
||||
/// Finally, requiring TLS use with valid certificates may be something of a nuisance in
|
||||
/// development settings, so you may with to restrict HSTS use to [Staging] and [Production].
|
||||
///
|
||||
/// [TLS]: https://rocket.rs/guide/configuration/#configuring-tls
|
||||
/// [Strict-Transport-Security]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
|
||||
/// [default policy]: /rocket_contrib/space_helmet/enum.HstsPolicy.html#impl-Default
|
||||
/// [Yelp engineering]: https://engineeringblog.yelp.com/2017/09/the-road-to-hsts.html
|
||||
/// [Staging]: /rocket/config/enum.Environment.html#variant.Staging
|
||||
/// [Production]: /rocket/config/enum.Environment.html#variant.Production
|
||||
pub enum HstsPolicy {
|
||||
/// Browser should only permit this site to be accesses by HTTPS for the next [`Duration`]
|
||||
/// seconds.
|
||||
Enable(Duration),
|
||||
|
||||
/// Same as above, but also apply to all of the sites subdomains.
|
||||
IncludeSubDomains(Duration),
|
||||
|
||||
/// Google maintains an [HSTS preload service] that can be used to prevent
|
||||
/// the browser from ever connecting to your site over an insecure connection.
|
||||
/// Read more [here]. Don't enable this before you have registered your site
|
||||
///
|
||||
/// [HSTS preload service]: https://hstspreload.org/
|
||||
/// [here]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#Preloading_Strict_Transport_Security
|
||||
Preload(Duration),
|
||||
}
|
||||
|
||||
/// Defaults to `HstsPolicy::Enable(Duration::weeks(52))`.
|
||||
impl Default for HstsPolicy {
|
||||
fn default() -> HstsPolicy {
|
||||
HstsPolicy::Enable(Duration::weeks(52))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<&'a HstsPolicy> for Header<'b> {
|
||||
fn from(policy: &HstsPolicy) -> Header<'b> {
|
||||
let policy_string = match policy {
|
||||
HstsPolicy::Enable(max_age) => format!("max-age={}", max_age.num_seconds()),
|
||||
HstsPolicy::IncludeSubDomains(max_age) => {
|
||||
format!("max-age={}; includeSubDomains", max_age.num_seconds())
|
||||
}
|
||||
HstsPolicy::Preload(max_age) => format!("max-age={}; preload", max_age.num_seconds()),
|
||||
};
|
||||
|
||||
Header::new("Strict-Transport-Security", policy_string)
|
||||
}
|
||||
}
|
||||
|
||||
/// The [X-Frame-Options] header controls whether the browser should allow the page
|
||||
/// to render in a `<frame>`, [`<iframe>`][iframe] or `<object>`. This can be used
|
||||
/// to prevent [clickjacking] attacks.
|
||||
///
|
||||
///
|
||||
/// [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
||||
/// [clickjacking]: https://en.wikipedia.org/wiki/Clickjacking
|
||||
/// [owasp-clickjacking]: https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet
|
||||
/// [iframe]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
|
||||
pub enum FramePolicy<'a> {
|
||||
/// Page cannot be displayed in a frame.
|
||||
Deny,
|
||||
|
||||
/// Page can only be displayed in a frame if the page trying to render it came from
|
||||
/// the same-origin. Interpretation of same-origin is [browser dependant][X-Frame-Options].
|
||||
///
|
||||
/// [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
||||
SameOrigin,
|
||||
|
||||
/// Page can only be displayed in a frame if the page trying to render it came from
|
||||
/// the origin given `Uri`. Interpretation of origin is [browser dependant][X-Frame-Options].
|
||||
///
|
||||
/// [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
||||
AllowFrom(Uri<'a>),
|
||||
}
|
||||
|
||||
///Defaults to [`FramePolicy::SameOrigin`].
|
||||
impl<'a> Default for FramePolicy<'a> {
|
||||
fn default() -> FramePolicy<'a> {
|
||||
FramePolicy::SameOrigin
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<&'a FramePolicy<'a>> for Header<'b> {
|
||||
fn from(policy: &FramePolicy<'a>) -> Header<'b> {
|
||||
let policy_string: Cow<'static, str> = match policy {
|
||||
FramePolicy::Deny => "DENY".into(),
|
||||
FramePolicy::SameOrigin => "SAMEORIGIN".into(),
|
||||
FramePolicy::AllowFrom(uri) => format!("ALLOW-FROM {}", uri).into(),
|
||||
};
|
||||
|
||||
Header::new("X-Frame-Options", policy_string)
|
||||
}
|
||||
}
|
||||
|
||||
/// The [X-XSS-Protection] header tells the browsers to filter some forms of reflected
|
||||
/// XSS([cross-site scripting]) attacks.
|
||||
///
|
||||
/// [X-XSS-Protection]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
|
||||
/// [cross-site scripting]: https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting
|
||||
pub enum XssPolicy<'a> {
|
||||
/// Disables XSS filtering.
|
||||
Disable,
|
||||
|
||||
/// Enables XSS filtering, if XSS detected browser will sanitize and render page (_often browser
|
||||
/// default_).
|
||||
Enable,
|
||||
|
||||
/// Enables XSS filtering, if XSS detected browser will block rendering of page (_SpaceHelmet default_).
|
||||
EnableBlock,
|
||||
|
||||
/// Enables XSS filtering, if XSS detected browser will sanitize and render page and report the
|
||||
/// violation to the given `Uri`. (Chromium only)
|
||||
EnableReport(Uri<'a>),
|
||||
}
|
||||
|
||||
/// Defaults to [`XssPolicy::EnableBlock`], turns on XSS filtering and blocks page rendering if
|
||||
/// detected.
|
||||
impl<'a> Default for XssPolicy<'a> {
|
||||
fn default() -> XssPolicy<'a> {
|
||||
XssPolicy::EnableBlock
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<&'a XssPolicy<'a>> for Header<'b> {
|
||||
fn from(policy: &XssPolicy) -> Header<'b> {
|
||||
let policy_string: Cow<'static, str> = match policy {
|
||||
XssPolicy::Disable => "0".into(),
|
||||
XssPolicy::Enable => "1".into(),
|
||||
XssPolicy::EnableBlock => "1; mode=block".into(),
|
||||
XssPolicy::EnableReport(u) => format!("{}{}", "1; report=", u).into(),
|
||||
};
|
||||
|
||||
Header::new("X-XSS-Protection", policy_string)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
#![cfg_attr(test, feature(plugin, decl_macro))]
|
||||
#![cfg_attr(test, plugin(rocket_codegen))]
|
||||
#![feature(proc_macro_non_items)]
|
||||
|
||||
#[macro_use] extern crate rocket;
|
||||
extern crate rocket_contrib;
|
||||
|
||||
#[cfg(feature = "space_helmet")]
|
||||
extern crate time;
|
||||
|
||||
#[cfg(feature = "space_helmet")]
|
||||
mod space_helmet_tests {
|
||||
use rocket;
|
||||
use rocket::http::uri::Uri;
|
||||
use rocket::http::Status;
|
||||
use rocket::local::Client;
|
||||
use rocket_contrib::space_helmet::*;
|
||||
use time::Duration;
|
||||
|
||||
#[get("/")]
|
||||
fn hello() -> &'static str {
|
||||
"Hello, world!"
|
||||
}
|
||||
|
||||
macro_rules! check_header {
|
||||
($response:ident, $header_name:expr, $header_param:expr) => {
|
||||
match $response.headers().get_one($header_name) {
|
||||
Some(string) => assert_eq!(string, $header_param),
|
||||
None => panic!("missing header parameters")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_headers_test() {
|
||||
let helmet = SpaceHelmet::new();
|
||||
let rocket = rocket::ignite().mount("/", routes![hello]).attach(helmet);
|
||||
let client = Client::new(rocket).unwrap();
|
||||
let mut response = client.get("/").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.body_string(), Some("Hello, world!".into()));
|
||||
check_header!(response, "X-XSS-Protection", "1; mode=block");
|
||||
check_header!(response, "X-Frame-Options", "SAMEORIGIN");
|
||||
check_header!(response, "X-Content-Type-Options", "nosniff");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn additional_headers_test() {
|
||||
let helmet = SpaceHelmet::new()
|
||||
.hsts(HstsPolicy::default())
|
||||
.expect_ct(ExpectCtPolicy::default())
|
||||
.referrer_policy(ReferrerPolicy::default());
|
||||
let rocket = rocket::ignite().mount("/", routes![hello]).attach(helmet);
|
||||
let client = Client::new(rocket).unwrap();
|
||||
let mut response = client.get("/").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.body_string(), Some("Hello, world!".into()));
|
||||
check_header!(
|
||||
response,
|
||||
"Strict-Transport-Security",
|
||||
format!("max-age={}", Duration::weeks(52).num_seconds())
|
||||
);
|
||||
check_header!(
|
||||
response,
|
||||
"Expect-CT",
|
||||
format!("max-age={}, enforce", Duration::days(30).num_seconds())
|
||||
);
|
||||
check_header!(response, "Referrer-Policy", "no-referrer");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uri_test() {
|
||||
let allow_uri = Uri::parse("https://www.google.com").unwrap();
|
||||
let report_uri = Uri::parse("https://www.google.com").unwrap();
|
||||
let enforce_uri = Uri::parse("https://www.google.com").unwrap();
|
||||
let helmet = SpaceHelmet::new()
|
||||
.frameguard(FramePolicy::AllowFrom(allow_uri))
|
||||
.xss_protect(XssPolicy::EnableReport(report_uri))
|
||||
.expect_ct(ExpectCtPolicy::ReportAndEnforce(Duration::seconds(30), enforce_uri));
|
||||
let rocket = rocket::ignite().mount("/", routes![hello]).attach(helmet);
|
||||
let client = Client::new(rocket).unwrap();
|
||||
let response = client.get("/").dispatch();
|
||||
check_header!(
|
||||
response,
|
||||
"X-Frame-Options",
|
||||
"ALLOW-FROM https://www.google.com"
|
||||
);
|
||||
check_header!(
|
||||
response,
|
||||
"X-XSS-Protection",
|
||||
"1; report=https://www.google.com"
|
||||
);
|
||||
check_header!(
|
||||
response,
|
||||
"Expect-CT",
|
||||
"max-age=30, enforce, report-uri=\"https://www.google.com\""
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "space_helmet"
|
||||
version = "0.0.0"
|
||||
workspace = "../../"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
rocket = { path = "../../core/lib", features = ["tls"]}
|
||||
rocket_codegen = { path = "../../core/codegen" }
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
path = "../../contrib/lib"
|
||||
default-features = false
|
||||
features = ["space_helmet"]
|
||||
|
||||
[[bin]]
|
||||
name = "hello"
|
||||
path = "src/hello.rs"
|
|
@ -0,0 +1,4 @@
|
|||
# Example cert and key pair from the tls example, NEVER use these in production, for demonstration only!!!
|
||||
[global.tls]
|
||||
certs = "private/cert.pem"
|
||||
key = "private/key.pem"
|
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFITCCAwmgAwIBAgIJAII1fQkonYEEMA0GCSqGSIb3DQEBCwUAMEcxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEChMJUm9ja2V0IENBMRcwFQYDVQQD
|
||||
Ew5Sb2NrZXQgUm9vdCBDQTAeFw0xNzA5MDExMDAyMjhaFw0yNzA4MzAxMDAyMjha
|
||||
MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGUm9ja2V0MRIw
|
||||
EAYDVQQDEwlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
|
||||
AQDqe/Ps0tJf11HBuxJ4HvgC4VJeeiSl3D4P8ZT6uamCj8XD0MPtfRjGgfZPRjfY
|
||||
ksiYRs4Wg3Wy3aiQR6IVrNAxtfU1ZA3vRGCBwV0oWkfyPJKQOtF0Ih0/MhmYdiWG
|
||||
gDqs5qF/6B9K8qbinexal8v1oXpwQC5dod/NOuSLZQtQfkiYIeNqo0BbxtcaNE2u
|
||||
kgOYg1Cvc9ui3KPNA2JTN+Uzq6A8n4Pej6erG2NeCAoov9nrkPyustDWLQ76wdTp
|
||||
5YU6zwwsl+fJtb5scNUmagujoXTTqn06WoCMDUsSjC/jlGMIrzmx90Wq8Dg6HBGn
|
||||
Cscz3M/AUXYzJtShkxMNZCsdxH+8x5oyO/RrtyeRyN8iDiOolz+SfQROVXMU0zkx
|
||||
nRl7hIxgB/QeDi6MMXGLTd08vpIAohk3hnycsGgTwTCT5LxWJnorpm4wdr1bDmCY
|
||||
InUO5hX0rFWtS0ij78GTUbpajkNTEXIXXwa1VnSE2kIeUX6aiKhJsm3KWp496JuM
|
||||
ahIR7XCP9PyGclWI+Pa0eq5L8nnuSfqUAwCeOvvwdBOxUvKmecly1IHLoUXGnhy0
|
||||
46MjYo80yYFqrGgop6lUEZ0ThYpDpMxq+JIeUoyGaCJFDvundzt0u0sh9i+hUCVe
|
||||
v3zsgxwvBeJy0L1G1uGkpCqERkYJQt9O+qLM8i7hf7ONkQIDAQABoxgwFjAUBgNV
|
||||
HREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggIBAAcXycXdWVvwLl+7
|
||||
ryG8V7FpB9bp0lHNA4q3DpEINCNyuA2cbnVU/u2L3ddvroTcrPjE+hhNbcVaz/NH
|
||||
w4sQqlDzkV+G9kZ4qBTlk5zon6aGGow181J+B5SVznt6lO4/KYYpEN0vX+uMvsgK
|
||||
OG7ydsRMDxPpsnVS9SFx0Ke8AlmUet5S/NGYCfedd4rwCu+oJHUWhXNwFZqLF3Yn
|
||||
s8lg3xdM0kJt8g4m1/KUpunanX3w+DdZaIwbltEZs4NriXn0VVbEPRpHyiGMosgf
|
||||
mEUV2z49f6S2joEnSn2Y/ILOdKFQ2mKFXtXJP43Qzj8Mr5mSb2bXyABlrn0pl/+o
|
||||
HBkyVyDx5BKqWKe5uK3YCDsbIJj026AkCdTKF+BSBWfB+EqdSIOvVrpHtQK7BwFx
|
||||
pS5rdQBLA86f1NC0e235L6pwFKm+imazr6Jn7fbbwq1y9PSL36rUn4e/+R2Yoia9
|
||||
S7zDOqGbnyv9h7eE3Muiy26kJsJfCrjse/dmce+6YnB1FC5RKPn7kM86t7MyDrgx
|
||||
W60xRMdgmcGfPjei2V4MdVM6ysOlNoeh39DizjkV9+r8iGl4vngplJrPgAIvywQz
|
||||
v1pLk6dSlSOwgqY94hqxqNvG80xSoYsmMjDrPmtBVERjhbffsdIDHjcPVsJKH6l6
|
||||
8wg+/u6aK2bMHt41f3XE/UTY+A57
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,33 @@
|
|||
#![feature(decl_macro)]
|
||||
#![feature(plugin)]
|
||||
#![plugin(rocket_codegen)]
|
||||
#![feature(proc_macro_non_items)]
|
||||
|
||||
#[macro_use] extern crate rocket;
|
||||
extern crate rocket_contrib;
|
||||
use rocket::http::uri::Uri;
|
||||
|
||||
use rocket_contrib::space_helmet::*;
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> &'static str {
|
||||
"Hello, world!"
|
||||
}
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
let allow_uri = Uri::parse("https://mysite.example.com").unwrap();
|
||||
let report_uri = Uri::parse("https://report.example.com").unwrap();
|
||||
let helmet = SpaceHelmet::new()
|
||||
//illustrates how to disable a header by using None as the policy.
|
||||
.no_sniff(None)
|
||||
.frameguard(FramePolicy::AllowFrom(allow_uri))
|
||||
.xss_protect(XssPolicy::EnableReport(report_uri))
|
||||
//we need an hsts policy as we are using tls
|
||||
.hsts(HstsPolicy::default())
|
||||
.expect_ct(ExpectCtPolicy::default());
|
||||
rocket::ignite().mount("/", routes![index]).attach(helmet)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rocket().launch();
|
||||
}
|
|
@ -86,6 +86,7 @@ if [ "$1" = "--contrib" ]; then
|
|||
tera_templates
|
||||
handlebars_templates
|
||||
serve
|
||||
space_helmet
|
||||
diesel_postgres_pool
|
||||
diesel_sqlite_pool
|
||||
diesel_mysql_pool
|
||||
|
|
Loading…
Reference in New Issue