Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Fuzz Tests

on:
pull_request:
branches: ["main"]
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the intent behind this? Don't Actions runners have colors enabled by default?


permissions:
contents: read

jobs:
fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Install Rust nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true

- name: Install cargo-fuzz
run: cargo install cargo-fuzz

- name: Run fuzz_query_parser (2 min)
run: cargo +nightly fuzz run fuzz_query_parser -- -max_total_time=120
continue-on-error: false

- name: Run fuzz_token_validator (2 min)
run: cargo +nightly fuzz run fuzz_token_validator -- -max_total_time=120
continue-on-error: false

- name: Upload crash artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: fuzz-crashes-${{ github.sha }}
path: fuzz/artifacts/
retention-days: 30
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
resolver = "2"

members = ["aws_secretsmanager_agent", "aws_secretsmanager_caching", "integration-tests"]
exclude = ["fuzz"]
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,12 @@ For an agent architecture, the domain of trust is where the agent endpoint and S

Security conscious applications that are not already using an agent solution with the Secrets Manager credentials locked down to the application should consider using the language\-specific AWS SDKs or caching solutions\. For more information, see [Get secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets.html)\.

## Fuzz Testing<a name="fuzz-testing"></a>

The AWS Secrets Manager Agent includes fuzz tests to discover security vulnerabilities and edge cases by feeding malformed inputs to critical components. Fuzz tests run automatically on every pull request.

For detailed instructions on running fuzz tests locally, reproducing crashes, and managing the corpus, see [fuzz/README.md](fuzz/README.md).

## Running Integration Tests Locally<a name="integration-tests-local"></a>

The AWS Secrets Manager Agent includes a comprehensive integration test suite that validates functionality against real AWS Secrets Manager. These tests cover caching behavior, security features, configuration options, version management, and error handling scenarios.
Expand Down
3 changes: 3 additions & 0 deletions aws_secretsmanager_agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ homepage = "https://github.com/aws/aws-secretsmanager-agent"
repository = "https://github.com/aws/aws-secretsmanager-agent"
readme = "../README.md"

[lib]
doctest = false

[dependencies]
hyper = { version = "1", features = ["http1", "server"] }
tokio = { version = "1", features = ["rt-multi-thread", "net", "macros"] }
Expand Down
2 changes: 1 addition & 1 deletion aws_secretsmanager_agent/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[derive(Debug)]
pub(crate) struct HttpError(pub u16, pub String);
pub struct HttpError(pub u16, pub String);

impl From<url::ParseError> for HttpError {
fn from(e: url::ParseError) -> Self {
Expand Down
15 changes: 15 additions & 0 deletions aws_secretsmanager_agent/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Library interface for the AWS Secrets Manager Agent
// This exposes internal modules for testing and fuzzing purposes

pub mod cache_manager;
pub mod config;
pub mod constants;
pub mod error;
pub mod logging;
pub mod parse;
pub mod server;
pub mod utils;

// Re-export key types and functions for fuzzing
pub use parse::GSVQuery;
pub use utils::get_token;
6 changes: 3 additions & 3 deletions aws_secretsmanager_agent/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use url::Url;
use crate::error::HttpError;

#[derive(Debug)]
pub(crate) struct GSVQuery {
pub struct GSVQuery {
pub secret_id: String,
pub version_id: Option<String>,
pub version_stage: Option<String>,
Expand All @@ -23,7 +23,7 @@ impl GSVQuery {
}
}

pub(crate) fn try_from_query(s: &str) -> Result<Self, HttpError> {
pub fn try_from_query(s: &str) -> Result<Self, HttpError> {
// url library can only parse complete URIs. The host/port/scheme used is irrelevant since it is not used
let complete_uri = format!("http://localhost{}", s);

Expand Down Expand Up @@ -53,7 +53,7 @@ impl GSVQuery {
Ok(query)
}

pub(crate) fn try_from_path_query(s: &str, path_prefix: &str) -> Result<Self, HttpError> {
pub fn try_from_path_query(s: &str, path_prefix: &str) -> Result<Self, HttpError> {
// url library can only parse complete URIs. The host/port/scheme used is irrelevant since it gets stripped
let complete_uri = format!("http://localhost{}", s);

Expand Down
1 change: 0 additions & 1 deletion aws_secretsmanager_agent/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ pub fn err_response(err_code: &str, msg: &str) -> String {
///
/// * `Ok(String)` - The SSRF token value.
/// * `Err(Error)` - Error indicating that the variable is not set or could not be read.
#[doc(hidden)]
pub fn get_token(config: &Config) -> Result<String, Box<dyn std::error::Error>> {
// Iterate through the env name list looking for the first variable set
#[allow(clippy::redundant_closure)]
Expand Down
6 changes: 6 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
target
artifacts
coverage

# Ignore generated corpus files (40-char SHA-1 hashes, keep seed corpus)
corpus/*/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]
Loading
Loading