Struct Certificate
pub struct Certificate<'a> { /* private fields */ }
mtls
only.Expand description
A request guard for validated, verified client certificates.
This type is a wrapper over x509::TbsCertificate
with convenient
methods and complete documentation. Should the data exposed by the inherent
methods not suffice, this type derefs to x509::TbsCertificate
.
§Request Guard
The request guard implementation succeeds if:
- The client presents certificates.
- The certificates are active and not yet expired.
- The client’s certificate chain was signed by the CA identified by the
configured
ca_certs
and with respect to SNI, if any. See module level docs for configuration details.
If the client does not present certificates, the guard forwards with a status of 401 Unauthorized.
If the certificate chain fails to validate or verify, the guard fails with
the respective Error
.
§Wrapping
To implement roles, the Certificate
guard can be wrapped with a more
semantically meaningful type with extra validation. For example, if a
certificate with a specific serial number is known to belong to an
administrator, a CertifiedAdmin
type can authorize as follow:
use rocket::mtls::{self, bigint::BigUint, Certificate};
use rocket::request::{Request, FromRequest, Outcome};
use rocket::outcome::try_outcome;
use rocket::http::Status;
// The serial number for the certificate issued to the admin.
const ADMIN_SERIAL: &str = "65828378108300243895479600452308786010218223563";
// A request guard that authenticates and authorizes an administrator.
struct CertifiedAdmin<'r>(Certificate<'r>);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for CertifiedAdmin<'r> {
type Error = mtls::Error;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let cert = try_outcome!(req.guard::<Certificate<'r>>().await);
if let Some(true) = cert.has_serial(ADMIN_SERIAL) {
Outcome::Success(CertifiedAdmin(cert))
} else {
Outcome::Forward(Status::Unauthorized)
}
}
}
#[get("/admin")]
fn admin(admin: CertifiedAdmin<'_>) {
// This handler can only execute if an admin is authenticated.
}
#[get("/admin", rank = 2)]
fn unauthorized(user: Option<Certificate<'_>>) {
// This handler always executes, whether there's a non-admin user that's
// authenticated (user = Some()) or not (user = None).
}
§Example
To retrieve certificate data in a route, use Certificate
as a guard:
use rocket::mtls::{self, Certificate};
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
// This handler only runs when a valid certificate was presented.
}
#[get("/maybe")]
fn maybe_auth(cert: Option<Certificate<'_>>) {
// This handler runs even if no certificate was presented or an invalid
// certificate was presented.
}
#[get("/ok")]
fn ok_auth(cert: mtls::Result<Certificate<'_>>) {
// This handler does not run if a certificate was not presented but
// _does_ run if a valid (Ok) or invalid (Err) one was presented.
}
Implementations§
§impl<'a> Certificate<'a>
impl<'a> Certificate<'a>
pub fn serial(&self) -> &BigUint
pub fn serial(&self) -> &BigUint
Returns the serial number of the X.509 certificate.
§Example
use rocket::mtls::Certificate;
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
let cert = cert.serial();
}
pub fn version(&self) -> u32
pub fn version(&self) -> u32
Returns the version of the X.509 certificate.
§Example
use rocket::mtls::Certificate;
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
let cert = cert.version();
}
pub fn subject(&self) -> &Name<'a>
pub fn subject(&self) -> &Name<'a>
Returns the subject (a “DN” or “Distinguished Name”) of the X.509 certificate.
§Example
use rocket::mtls::Certificate;
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
if let Some(name) = cert.subject().common_name() {
println!("Hello, {}!", name);
}
}
pub fn issuer(&self) -> &Name<'a>
pub fn issuer(&self) -> &Name<'a>
Returns the issuer (a “DN” or “Distinguished Name”) of the X.509 certificate.
§Example
use rocket::mtls::Certificate;
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
if let Some(name) = cert.issuer().common_name() {
println!("Issued by: {}", name);
}
}
pub fn extensions(&self) -> &[X509Extension<'a>]
pub fn extensions(&self) -> &[X509Extension<'a>]
Returns a slice of the extensions in the X.509 certificate.
§Example
use rocket::mtls::{oid, x509, Certificate};
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
let subject_alt = cert.extensions().iter()
.find(|e| e.oid == oid::OID_X509_EXT_SUBJECT_ALT_NAME)
.and_then(|e| match e.parsed_extension() {
x509::ParsedExtension::SubjectAlternativeName(s) => Some(s),
_ => None
});
if let Some(subject_alt) = subject_alt {
for name in &subject_alt.general_names {
if let x509::GeneralName::RFC822Name(name) = name {
println!("An email, perhaps? {}", name);
}
}
}
}
pub fn has_serial(&self, number: &str) -> Option<bool>
pub fn has_serial(&self, number: &str) -> Option<bool>
Checks if the certificate has the serial number number
.
If number
is not a valid unsigned integer in base 10, returns None
.
Otherwise, returns Some(true)
if it does and Some(false)
if it does
not.
use rocket::mtls::Certificate;
const SERIAL: &str = "65828378108300243895479600452308786010218223563";
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
if cert.has_serial(SERIAL).unwrap_or(false) {
println!("certificate has the expected serial number");
}
}
pub fn as_bytes(&self) -> &'a [u8] ⓘ
pub fn as_bytes(&self) -> &'a [u8] ⓘ
Returns the raw, unmodified, DER-encoded X.509 certificate data bytes.
§Example
use rocket::mtls::Certificate;
const SHA256_FINGERPRINT: &str =
"CE C2 4E 01 00 FF F7 78 CB A4 AA CB D2 49 DD 09 \
02 EF 0E 9B DA 89 2A E4 0D F4 09 83 97 C1 97 0D";
#[get("/auth")]
fn auth(cert: Certificate<'_>) {
if sha256_fingerprint(cert.as_bytes()) == SHA256_FINGERPRINT {
println!("certificate fingerprint matched");
}
}
Methods from Deref<Target = TbsCertificate<'a>>§
Sourcepub fn version(&self) -> X509Version
pub fn version(&self) -> X509Version
Get the version of the encoded certificate
Sourcepub fn public_key(&self) -> &SubjectPublicKeyInfo<'_>
pub fn public_key(&self) -> &SubjectPublicKeyInfo<'_>
Get the certificate public key information.
Sourcepub fn extensions(&self) -> &[X509Extension<'a>]
pub fn extensions(&self) -> &[X509Extension<'a>]
Returns the certificate extensions
Sourcepub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension<'a>>
pub fn iter_extensions(&self) -> impl Iterator<Item = &X509Extension<'a>>
Returns an iterator over the certificate extensions
Sourcepub fn get_extension_unique(
&self,
oid: &Oid<'_>,
) -> Result<Option<&X509Extension<'a>>, X509Error>
pub fn get_extension_unique( &self, oid: &Oid<'_>, ) -> Result<Option<&X509Extension<'a>>, X509Error>
Searches for an extension with the given Oid
.
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error DuplicateExtensions
if the extension is present twice or more.
Sourcepub fn find_extension(&self, oid: &Oid<'_>) -> Option<&X509Extension<'a>>
👎Deprecated since 0.13.0: Do not use this function (duplicate extensions are not checked), use get_extension_unique
pub fn find_extension(&self, oid: &Oid<'_>) -> Option<&X509Extension<'a>>
get_extension_unique
Searches for an extension with the given Oid
.
§Duplicate extensions
Note: if there are several extensions with the same Oid
, the first one is returned, masking other values.
RFC5280 forbids having duplicate extensions, but does not specify how errors should be handled.
Because of this, the find_extension
method is not safe and should not be used!
The get_extension_unique
method checks for duplicate extensions and should be
preferred.
Sourcepub fn extensions_map(
&self,
) -> Result<HashMap<Oid<'_>, &X509Extension<'a>>, X509Error>
pub fn extensions_map( &self, ) -> Result<HashMap<Oid<'_>, &X509Extension<'a>>, X509Error>
Builds and returns a map of extensions.
If an extension is present twice, this will fail and return DuplicateExtensions
.
Sourcepub fn basic_constraints(
&self,
) -> Result<Option<BasicExtension<&BasicConstraints>>, X509Error>
pub fn basic_constraints( &self, ) -> Result<Option<BasicExtension<&BasicConstraints>>, X509Error>
Attempt to get the certificate Basic Constraints extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is present twice or more.
Sourcepub fn key_usage(&self) -> Result<Option<BasicExtension<&KeyUsage>>, X509Error>
pub fn key_usage(&self) -> Result<Option<BasicExtension<&KeyUsage>>, X509Error>
Attempt to get the certificate Key Usage extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn extended_key_usage(
&self,
) -> Result<Option<BasicExtension<&ExtendedKeyUsage<'_>>>, X509Error>
pub fn extended_key_usage( &self, ) -> Result<Option<BasicExtension<&ExtendedKeyUsage<'_>>>, X509Error>
Attempt to get the certificate Extended Key Usage extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn policy_constraints(
&self,
) -> Result<Option<BasicExtension<&PolicyConstraints>>, X509Error>
pub fn policy_constraints( &self, ) -> Result<Option<BasicExtension<&PolicyConstraints>>, X509Error>
Attempt to get the certificate Policy Constraints extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn inhibit_anypolicy(
&self,
) -> Result<Option<BasicExtension<&InhibitAnyPolicy>>, X509Error>
pub fn inhibit_anypolicy( &self, ) -> Result<Option<BasicExtension<&InhibitAnyPolicy>>, X509Error>
Attempt to get the certificate Policy Constraints extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn policy_mappings(
&self,
) -> Result<Option<BasicExtension<&PolicyMappings<'_>>>, X509Error>
pub fn policy_mappings( &self, ) -> Result<Option<BasicExtension<&PolicyMappings<'_>>>, X509Error>
Attempt to get the certificate Policy Mappings extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn subject_alternative_name(
&self,
) -> Result<Option<BasicExtension<&SubjectAlternativeName<'_>>>, X509Error>
pub fn subject_alternative_name( &self, ) -> Result<Option<BasicExtension<&SubjectAlternativeName<'_>>>, X509Error>
Attempt to get the certificate Subject Alternative Name extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn name_constraints(
&self,
) -> Result<Option<BasicExtension<&NameConstraints<'_>>>, X509Error>
pub fn name_constraints( &self, ) -> Result<Option<BasicExtension<&NameConstraints<'_>>>, X509Error>
Attempt to get the certificate Name Constraints extension
Return Ok(Some(extension))
if exactly one was found, Ok(None)
if none was found,
or an error if the extension is invalid, or is present twice or more.
Sourcepub fn raw_serial(&self) -> &'a [u8] ⓘ
pub fn raw_serial(&self) -> &'a [u8] ⓘ
Get the raw bytes of the certificate serial number
Sourcepub fn raw_serial_as_string(&self) -> String
pub fn raw_serial_as_string(&self) -> String
Get a formatted string of the certificate serial number, separated by ‘:’
Trait Implementations§
§impl<'a> Debug for Certificate<'a>
impl<'a> Debug for Certificate<'a>
§impl<'a> Deref for Certificate<'a>
impl<'a> Deref for Certificate<'a>
§type Target = TbsCertificate<'a>
type Target = TbsCertificate<'a>
§fn deref(&self) -> &<Certificate<'a> as Deref>::Target
fn deref(&self) -> &<Certificate<'a> as Deref>::Target
Source§impl<'r> FromRequest<'r> for Certificate<'r>
impl<'r> FromRequest<'r> for Certificate<'r>
§impl<'a> PartialEq for Certificate<'a>
impl<'a> PartialEq for Certificate<'a>
impl<'a> StructuralPartialEq for Certificate<'a>
Auto Trait Implementations§
impl<'a> Freeze for Certificate<'a>
impl<'a> RefUnwindSafe for Certificate<'a>
impl<'a> Send for Certificate<'a>
impl<'a> Sync for Certificate<'a>
impl<'a> Unpin for Certificate<'a>
impl<'a> UnwindSafe for Certificate<'a>
Blanket Implementations§
Source§impl<'a, T> AsTaggedExplicit<'a> for Twhere
T: 'a,
impl<'a, T> AsTaggedExplicit<'a> for Twhere
T: 'a,
Source§impl<'a, T> AsTaggedImplicit<'a> for Twhere
T: 'a,
impl<'a, T> AsTaggedImplicit<'a> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
§impl<T> IntoCollection<T> for T
impl<T> IntoCollection<T> for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the foreground set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red()
and
green()
, which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg()
:
use yansi::{Paint, Color};
painted.fg(Color::White);
Set foreground color to white using white()
.
use yansi::Paint;
painted.white();
Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightBlack
.
§Example
println!("{}", value.bright_black());
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightGreen
.
§Example
println!("{}", value.bright_green());
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightYellow
.
§Example
println!("{}", value.bright_yellow());
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightMagenta
.
§Example
println!("{}", value.bright_magenta());
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightWhite
.
§Example
println!("{}", value.bright_white());
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the background set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red()
and
on_green()
, which have the same functionality but
are pithier.
§Example
Set background color to red using fg()
:
use yansi::{Paint, Color};
painted.bg(Color::Red);
Set background color to red using on_red()
.
use yansi::Paint;
painted.on_red();
Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightBlack
.
§Example
println!("{}", value.on_bright_black());
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightGreen
.
§Example
println!("{}", value.on_bright_green());
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightYellow
.
§Example
println!("{}", value.on_bright_yellow());
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightBlue
.
§Example
println!("{}", value.on_bright_blue());
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightMagenta
.
§Example
println!("{}", value.on_bright_magenta());
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightCyan
.
§Example
println!("{}", value.on_bright_cyan());
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightWhite
.
§Example
println!("{}", value.on_bright_white());
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute
value
.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold()
and
underline()
, which have the same functionality
but are pithier.
§Example
Make text bold using attr()
:
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);
Make text bold using using bold()
.
use yansi::Paint;
painted.bold();
Source§fn underline(&self) -> Painted<&T>
fn underline(&self) -> Painted<&T>
Returns self
with the
attr()
set to
Attribute::Underline
.
§Example
println!("{}", value.underline());
Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Returns self
with the
attr()
set to
Attribute::RapidBlink
.
§Example
println!("{}", value.rapid_blink());
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi
Quirk
value
.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask()
and
wrap()
, which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk()
:
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);
Enable wrapping using wrap()
.
use yansi::Paint;
painted.wrap();
Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition
value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted
only when both stdout
and stderr
are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);