Skip to content

Commit a9b9cba

Browse files
author
Zelda Hessler
authored
Add new MRAP test to S3 canary (#3109)
This PR also replaces the `2023_09_25` canary with current release *(`2023_10_26`)* ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._
1 parent b684182 commit a9b9cba

File tree

14 files changed

+221
-92
lines changed

14 files changed

+221
-92
lines changed

tools/ci-cdk/canary-lambda/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ invoke the canary:
3434
3535
```bash
3636
export CANARY_S3_BUCKET_NAME=<your bucket name>
37+
export CANARY_S3_MRAP_BUCKET_ARN=<your MRAP bucket ARN>
3738
# run with `--all-features` so you run all canaries (including canaries that don't work against older versions)
3839
cargo run --all-features -- --local
3940
```

tools/ci-cdk/canary-lambda/src/canary.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub fn get_canaries_to_run(
5050

5151
pub struct CanaryEnv {
5252
pub(crate) s3_bucket_name: String,
53+
pub(crate) s3_mrap_bucket_arn: String,
5354
pub(crate) expected_transcribe_result: String,
5455
#[allow(dead_code)]
5556
pub(crate) page_size: usize,
@@ -59,6 +60,7 @@ impl fmt::Debug for CanaryEnv {
5960
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6061
f.debug_struct("CanaryEnv")
6162
.field("s3_bucket_name", &"*** redacted ***")
63+
.field("s3_mrap_bucket_arn", &"*** redacted ***")
6264
.field(
6365
"expected_transcribe_result",
6466
&self.expected_transcribe_result,
@@ -72,6 +74,9 @@ impl CanaryEnv {
7274
// S3 bucket name to test against
7375
let s3_bucket_name =
7476
env::var("CANARY_S3_BUCKET_NAME").expect("CANARY_S3_BUCKET_NAME must be set");
77+
// S3 MRAP bucket name to test against
78+
let s3_mrap_bucket_arn =
79+
env::var("CANARY_S3_MRAP_BUCKET_ARN").expect("CANARY_S3_MRAP_BUCKET_ARN must be set");
7580

7681
// Expected transcription from Amazon Transcribe from the embedded audio file.
7782
// This is an environment variable so that the code doesn't need to be changed if
@@ -89,6 +94,7 @@ impl CanaryEnv {
8994

9095
Self {
9196
s3_bucket_name,
97+
s3_mrap_bucket_arn,
9298
expected_transcribe_result,
9399
page_size,
94100
}

tools/ci-cdk/canary-lambda/src/latest/paginator_canary.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub async fn paginator_canary(client: ec2::Client, page_size: usize) -> anyhow::
3838
}
3939
num_pages += 1;
4040
}
41-
if dbg!(num_pages) < 2 {
41+
if num_pages < 2 {
4242
bail!(
4343
"expected 3+ pages containing ~60 results but got {} pages",
4444
num_pages
@@ -59,7 +59,7 @@ pub async fn paginator_canary(client: ec2::Client, page_size: usize) -> anyhow::
5959

6060
#[cfg(test)]
6161
mod test {
62-
use crate::latest::paginator_canary::paginator_canary;
62+
use super::paginator_canary;
6363

6464
#[tokio::test]
6565
async fn test_paginator() {

tools/ci-cdk/canary-lambda/src/latest/s3_canary.rs

Lines changed: 101 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{mk_canary, CanaryEnv};
88
use anyhow::Context;
99
use aws_config::SdkConfig;
1010
use aws_sdk_s3 as s3;
11+
use s3::config::Region;
1112
use s3::presigning::PresigningConfig;
1213
use s3::primitives::ByteStream;
1314
use std::time::Duration;
@@ -17,10 +18,15 @@ const METADATA_TEST_VALUE: &str = "some value";
1718

1819
mk_canary!("s3", |sdk_config: &SdkConfig, env: &CanaryEnv| s3_canary(
1920
s3::Client::new(sdk_config),
20-
env.s3_bucket_name.clone()
21+
env.s3_bucket_name.clone(),
22+
env.s3_mrap_bucket_arn.clone()
2123
));
2224

23-
pub async fn s3_canary(client: s3::Client, s3_bucket_name: String) -> anyhow::Result<()> {
25+
pub async fn s3_canary(
26+
client: s3::Client,
27+
s3_bucket_name: String,
28+
s3_mrap_bucket_arn: String,
29+
) -> anyhow::Result<()> {
2430
let test_key = Uuid::new_v4().as_u128().to_string();
2531

2632
// Look for the test object and expect that it doesn't exist
@@ -82,39 +88,104 @@ pub async fn s3_canary(client: s3::Client, s3_bucket_name: String) -> anyhow::Re
8288
return Err(CanaryError(format!("presigned URL returned bad data: {:?}", response)).into());
8389
}
8490

85-
let mut result = Ok(());
86-
match output.metadata() {
87-
Some(map) => {
88-
// Option::as_deref doesn't work here since the deref of &String is String
89-
let value = map.get("something").map(|s| s.as_str()).unwrap_or("");
90-
if value != METADATA_TEST_VALUE {
91-
result = Err(CanaryError(format!(
91+
let metadata_value = output
92+
.metadata()
93+
.and_then(|m| m.get("something"))
94+
.map(String::as_str);
95+
let result: anyhow::Result<()> = match metadata_value {
96+
Some(value) => {
97+
if value == METADATA_TEST_VALUE {
98+
let payload = output
99+
.body
100+
.collect()
101+
.await
102+
.context("download s3::GetObject[2] body")?
103+
.into_bytes();
104+
if std::str::from_utf8(payload.as_ref()).context("s3 payload")? == "test" {
105+
Ok(())
106+
} else {
107+
Err(CanaryError("S3 object body didn't match what was put there".into()).into())
108+
}
109+
} else {
110+
Err(CanaryError(format!(
92111
"S3 metadata was incorrect. Expected `{}` but got `{}`.",
93112
METADATA_TEST_VALUE, value
94113
))
95-
.into());
114+
.into())
96115
}
97116
}
98-
None => {
99-
result = Err(CanaryError("S3 metadata was missing".into()).into());
100-
}
101-
}
117+
None => Err(CanaryError("S3 metadata was missing".into()).into()),
118+
};
102119

103-
let payload = output
104-
.body
105-
.collect()
120+
// Delete the test object
121+
client
122+
.delete_object()
123+
.bucket(&s3_bucket_name)
124+
.key(&test_key)
125+
.send()
106126
.await
107-
.context("download s3::GetObject[2] body")?
108-
.into_bytes();
109-
if std::str::from_utf8(payload.as_ref()).context("s3 payload")? != "test" {
110-
result = Err(CanaryError("S3 object body didn't match what was put there".into()).into());
111-
}
127+
.context("s3::DeleteObject")?;
128+
129+
// Return early if the result is an error
130+
result?;
131+
132+
// We deliberately use a region that doesn't exist here so that we can
133+
// ensure these requests are SigV4a requests. Because the current endpoint
134+
// resolver always resolves the wildcard region ('*') for SigV4a requests,
135+
// setting a fictitious region ensures that the request would fail if it was
136+
// a SigV4 request. Therefore, because the request doesn't fail, we can be
137+
// sure it's a successful Sigv4a request.
138+
let config_override = s3::Config::builder().region(Region::new("parts-unknown"));
139+
// Put the test object
140+
client
141+
.put_object()
142+
.bucket(&s3_mrap_bucket_arn)
143+
.key(&test_key)
144+
.body(ByteStream::from_static(b"test"))
145+
.metadata("something", METADATA_TEST_VALUE)
146+
.customize()
147+
.config_override(config_override.clone())
148+
.send()
149+
.await
150+
.context("s3::PutObject[MRAP]")?;
151+
152+
// Get the test object and verify it looks correct
153+
let output = client
154+
.get_object()
155+
.bucket(&s3_mrap_bucket_arn)
156+
.key(&test_key)
157+
.customize()
158+
.config_override(config_override.clone())
159+
.send()
160+
.await
161+
.context("s3::GetObject[MRAP]")?;
162+
163+
let metadata_value = output
164+
.metadata()
165+
.and_then(|m| m.get("something"))
166+
.map(String::as_str);
167+
let result = match metadata_value {
168+
Some(value) => {
169+
if value == METADATA_TEST_VALUE {
170+
Ok(())
171+
} else {
172+
Err(CanaryError(format!(
173+
"S3 metadata was incorrect. Expected `{}` but got `{}`.",
174+
METADATA_TEST_VALUE, value
175+
))
176+
.into())
177+
}
178+
}
179+
None => Err(CanaryError("S3 metadata was missing".into()).into()),
180+
};
112181

113182
// Delete the test object
114183
client
115184
.delete_object()
116-
.bucket(&s3_bucket_name)
185+
.bucket(&s3_mrap_bucket_arn)
117186
.key(&test_key)
187+
.customize()
188+
.config_override(config_override)
118189
.send()
119190
.await
120191
.context("s3::DeleteObject")?;
@@ -123,8 +194,12 @@ pub async fn s3_canary(client: s3::Client, s3_bucket_name: String) -> anyhow::Re
123194
}
124195

125196
// This test runs against an actual AWS account. Comment out the `ignore` to run it.
126-
// Be sure to set the `TEST_S3_BUCKET` environment variable to the S3 bucket to use,
127-
// and also make sure the credential profile sets the region (or set `AWS_DEFAULT_PROFILE`).
197+
// Be sure the following environment variables are set:
198+
//
199+
// - `TEST_S3_BUCKET`: The S3 bucket to use
200+
// - `TEST_S3_MRAP_BUCKET_ARN`: The MRAP bucket ARN to use
201+
//
202+
// Also, make sure the correct region (likely `us-west-2`) by the credentials or explictly.
128203
#[ignore]
129204
#[cfg(test)]
130205
#[tokio::test]
@@ -134,6 +209,7 @@ async fn test_s3_canary() {
134209
s3_canary(
135210
client,
136211
std::env::var("TEST_S3_BUCKET").expect("TEST_S3_BUCKET must be set"),
212+
std::env::var("TEST_S3_MRAP_BUCKET_ARN").expect("TEST_S3_MRAP_BUCKET_ARN must be set"),
137213
)
138214
.await
139215
.expect("success");

tools/ci-cdk/canary-lambda/src/main.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ mod latest;
2626
#[cfg(feature = "latest")]
2727
pub(crate) use latest as current_canary;
2828

29-
// NOTE: This module can be deleted 3 releases after release-2023-09-25
30-
#[cfg(feature = "release-2023-09-25")]
31-
mod release_2023_09_25;
32-
#[cfg(feature = "release-2023-09-25")]
33-
pub(crate) use release_2023_09_25 as current_canary;
29+
// NOTE: This module can be deleted 3 releases after release-2023-10-26
30+
#[cfg(feature = "release-2023-10-26")]
31+
mod release_2023_10_26;
32+
#[cfg(feature = "release-2023-10-26")]
33+
pub(crate) use release_2023_10_26 as current_canary;
3434

3535
#[tokio::main]
3636
async fn main() -> Result<(), Error> {

tools/ci-cdk/canary-lambda/src/release_2023_09_25/paginator_canary.rs renamed to tools/ci-cdk/canary-lambda/src/release_2023_10_26/paginator_canary.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use aws_sdk_ec2 as ec2;
1010
use aws_sdk_ec2::types::InstanceType;
1111

1212
use crate::CanaryEnv;
13-
use tokio_stream::StreamExt;
1413

1514
mk_canary!(
1615
"ec2_paginator",
@@ -39,7 +38,7 @@ pub async fn paginator_canary(client: ec2::Client, page_size: usize) -> anyhow::
3938
}
4039
num_pages += 1;
4140
}
42-
if dbg!(num_pages) < 2 {
41+
if num_pages < 2 {
4342
bail!(
4443
"expected 3+ pages containing ~60 results but got {} pages",
4544
num_pages
@@ -60,7 +59,7 @@ pub async fn paginator_canary(client: ec2::Client, page_size: usize) -> anyhow::
6059

6160
#[cfg(test)]
6261
mod test {
63-
use crate::current_canary::paginator_canary::paginator_canary;
62+
use super::paginator_canary;
6463

6564
#[tokio::test]
6665
async fn test_paginator() {

tools/ci-cdk/canary-runner/src/build_bundle.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const REQUIRED_SDK_CRATES: &[&str] = &[
6666
// The elements in this `Vec` should be sorted in an ascending order by the release date.
6767
lazy_static! {
6868
static ref NOTABLE_SDK_RELEASE_TAGS: Vec<ReleaseTag> = vec![
69-
ReleaseTag::from_str("release-2023-09-25").unwrap(), // last version before `Stream` trait removal
69+
ReleaseTag::from_str("release-2023-10-26").unwrap(), // last version before addition of Sigv4a MRAP test
7070
];
7171
}
7272

@@ -442,7 +442,7 @@ aws-sdk-transcribestreaming = { path = "some/sdk/path/transcribestreaming" }
442442
443443
[features]
444444
latest = []
445-
"release-2023-09-25" = []
445+
"release-2023-10-26" = []
446446
default = ["latest"]
447447
"#,
448448
generate_crate_manifest(CrateSource::Path("some/sdk/path".into())).expect("success")
@@ -506,7 +506,7 @@ aws-sdk-transcribestreaming = "0.16.0"
506506
507507
[features]
508508
latest = []
509-
"release-2023-09-25" = []
509+
"release-2023-10-26" = []
510510
default = ["latest"]
511511
"#,
512512
generate_crate_manifest(CrateSource::VersionsManifest {
@@ -585,14 +585,14 @@ default = ["latest"]
585585
}),
586586
);
587587
assert_eq!(
588-
"release-2023-09-25".to_string(),
588+
"release-2023-10-26".to_string(),
589589
enabled_feature(&CrateSource::VersionsManifest {
590590
versions: versions.clone(),
591-
release_tag: "release-2023-09-25".parse().unwrap(),
591+
release_tag: "release-2023-10-26".parse().unwrap(),
592592
}),
593593
);
594594
assert_eq!(
595-
"release-2023-09-25".to_string(),
595+
"release-2023-10-26".to_string(),
596596
enabled_feature(&CrateSource::VersionsManifest {
597597
versions,
598598
release_tag: "release-2023-01-13".parse().unwrap(),

0 commit comments

Comments
 (0)