Skip to content

Commit 9275b0d

Browse files
committed
Add migration, start setting stability
This adds a migration guide (as a doc-only module, migration.rs). Various parts of the library are not intended for typical use but _could_ be useful for others doing AWS SigV4 hacking. These items are gated behind the `unstable` feature, which is not enabled by default.
1 parent 8de2d82 commit 9275b0d

10 files changed

+276
-88
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ readme = "README.md"
1414
[lib]
1515
name = "scratchstack_aws_signature"
1616

17+
[features]
18+
default = []
19+
unstable = []
20+
1721
[dependencies]
1822
async-trait = "^0.1"
1923
bytes = "^1.6"

src/auth.rs

+40-25
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! AWS API request signatures verification routines.
22
//!
3-
//! This is essentially the server-side complement of [rusoto_signature](https://crates.io/crates/rusoto_signature)
4-
//! but follows the implementation of [python-aws-sig](https://github.com/dacut/python-aws-sig).
5-
//!
63
//! This implements the AWS [SigV4](http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)
74
//! and [SigV4S3](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)
8-
//! algorithms.
5+
//! server-side validation algorithms.
96
//!
7+
//! **Stability of this module is not guaranteed except for items exposed at the crate root**.
8+
//! The functions and types are subject to change in minor/patch versions. This is exposed for
9+
//! testing purposes only.
1010
1111
use {
1212
crate::{crypto::hmac_sha256, GetSigningKeyRequest, GetSigningKeyResponse, SignatureError},
@@ -49,15 +49,16 @@ const SHA256_EMPTY: &str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495
4949
const SHA256_HEX_LENGTH: usize = SHA256_EMPTY.len();
5050

5151
/// Low-level structure for performing AWS SigV4 authentication after a canonical request has been generated.
52+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
5253
#[derive(Builder, Clone, Default)]
5354
#[builder(derive(Debug))]
5455
pub struct SigV4Authenticator {
5556
/// The SHA-256 hash of the canonical request.
5657
canonical_request_sha256: [u8; SHA256_OUTPUT_LEN],
5758

5859
/// The credential passed into the request, in the form of `keyid/date/region/service/aws4_request`.
59-
/// This is allowed to be invalid upon creation since the validation of the credential is performed _after_ the
60-
/// validation of the request timestamp.
60+
/// The date must reflect that of the request timestamp in `YYYYMMDD` format, not the server's
61+
/// date. Timestamp validation is performed separately.
6162
credential: String,
6263

6364
/// The optional session token.
@@ -73,43 +74,51 @@ pub struct SigV4Authenticator {
7374

7475
impl SigV4Authenticator {
7576
/// Create a builder for `SigV4Authenticator`.
77+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
78+
#[inline(always)]
7679
pub fn builder() -> SigV4AuthenticatorBuilder {
7780
SigV4AuthenticatorBuilder::default()
7881
}
7982

8083
/// Retrieve the SHA-256 hash of the canonical request.
81-
#[inline]
84+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
85+
#[inline(always)]
8286
pub fn canonical_request_sha256(&self) -> [u8; SHA256_OUTPUT_LEN] {
8387
self.canonical_request_sha256
8488
}
8589

8690
/// Retrieve the credential passed into the request, in the form of `keyid/date/region/service/aws4_request`.
87-
#[inline]
91+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
92+
#[inline(always)]
8893
pub fn credential(&self) -> &str {
8994
&self.credential
9095
}
9196

9297
/// Retrieve the optional session token.
93-
#[inline]
98+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
99+
#[inline(always)]
94100
pub fn session_token(&self) -> Option<&str> {
95101
self.session_token.as_deref()
96102
}
97103

98104
/// Retrieve the signature passed into the request.
99-
#[inline]
105+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
106+
#[inline(always)]
100107
pub fn signature(&self) -> &str {
101108
&self.signature
102109
}
103110

104111
/// Retrieve the timestamp of the request.
105-
#[inline]
112+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
113+
#[inline(always)]
106114
pub fn request_timestamp(&self) -> DateTime<Utc> {
107115
self.request_timestamp
108116
}
109117

110118
/// Verify the request parameters make sense for the region, service, and specified timestamp.
111-
/// This must be called successfully before calling [validate_signature].
112-
fn prevalidate(
119+
/// This must be called successfully before calling [validate_signature][Self::validate_signature].
120+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
121+
pub fn prevalidate(
113122
&self,
114123
region: &str,
115124
service: &str,
@@ -205,8 +214,9 @@ impl SigV4Authenticator {
205214
}
206215

207216
/// Return the signing key (`kSigning` from the [AWS documentation](https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html))
208-
/// for the re
209-
async fn get_signing_key<S, F>(
217+
/// for the request.
218+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
219+
pub async fn get_signing_key<S, F>(
210220
&self,
211221
region: &str,
212222
service: &str,
@@ -242,7 +252,9 @@ impl SigV4Authenticator {
242252
}
243253
}
244254

245-
pub(crate) fn get_string_to_sign(&self) -> Vec<u8> {
255+
/// Return the string to sign for the request.
256+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
257+
pub fn get_string_to_sign(&self) -> Vec<u8> {
246258
let mut result = Vec::with_capacity(
247259
AWS4_HMAC_SHA256.len() + 1 + ISO8601_UTC_LENGTH + 1 + self.credential.len() + 1 + SHA256_HEX_LENGTH,
248260
);
@@ -263,6 +275,7 @@ impl SigV4Authenticator {
263275
}
264276

265277
/// Validate the request signature.
278+
#[cfg_attr(doc, doc(cfg(feature = "unstable")))]
266279
pub async fn validate_signature<S, F>(
267280
&self,
268281
region: &str,
@@ -303,18 +316,20 @@ impl Debug for SigV4Authenticator {
303316
}
304317
}
305318

306-
#[allow(dead_code)] // used in tests
307319
impl SigV4AuthenticatorBuilder {
308-
pub(crate) fn get_credential(&self) -> &Option<String> {
309-
&self.credential
320+
/// Retrieve the credential passed into the request.
321+
pub fn get_credential(&self) -> Option<&str> {
322+
self.credential.as_deref()
310323
}
311324

312-
pub(crate) fn get_signature(&self) -> &Option<String> {
313-
&self.signature
325+
/// Retrieve the signature passed into the request.
326+
pub fn get_signature(&self) -> Option<&str> {
327+
self.signature.as_deref()
314328
}
315329

316-
pub(crate) fn get_session_token(&self) -> &Option<Option<String>> {
317-
&self.session_token
330+
/// Retrieve the session token passed into the request.
331+
pub fn get_session_token(&self) -> Option<&str> {
332+
self.session_token.as_ref()?.as_deref()
318333
}
319334
}
320335

@@ -377,8 +392,8 @@ mod tests {
377392
use {
378393
super::duration_to_string,
379394
crate::{
380-
service_for_signing_key_fn, GetSigningKeyRequest, GetSigningKeyResponse, KSecretKey, SigV4Authenticator,
381-
SigV4AuthenticatorBuilder, SigV4AuthenticatorResponse, SignatureError,
395+
auth::{SigV4Authenticator, SigV4AuthenticatorBuilder, SigV4AuthenticatorResponse},
396+
service_for_signing_key_fn, GetSigningKeyRequest, GetSigningKeyResponse, KSecretKey, SignatureError,
382397
},
383398
chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, NaiveTime, Utc},
384399
log::LevelFilter,

src/aws4.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use {
22
crate::{
3-
service_for_signing_key_fn, sigv4_validate_request, CanonicalRequest, GetSigningKeyRequest,
3+
canonical::CanonicalRequest, service_for_signing_key_fn, sigv4_validate_request, GetSigningKeyRequest,
44
GetSigningKeyResponse, KSecretKey, SignatureOptions, NO_ADDITIONAL_SIGNED_HEADERS,
55
},
66
bytes::{Bytes, BytesMut},

0 commit comments

Comments
 (0)