Skip to content
Merged
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
6 changes: 5 additions & 1 deletion .asf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

github:
description: "Apache Reqsign: Signing HTTP requests without heavy SDKs."
homepage: https://docs.rs/reqsign
homepage: https://reqsign.apache.org
labels:
- rust
- s3
Expand Down Expand Up @@ -91,3 +91,7 @@ notifications:
issues: commits@reqsign.apache.org
pullrequests: commits@reqsign.apache.org
discussions: dev@reqsign.apache.org

# The generated website branch carries this file to enable ASF publishing.
publish:
whoami: asf-site
123 changes: 123 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

name: Website

on:
workflow_dispatch:
push:
branches:
- main
paths:
- ".asf.yaml"
- "website/**"
- ".github/workflows/website.yml"
# The provider catalog and included code snippets must stay in sync
# with the workspace, so Rust-side changes also validate the website.
- "Cargo.toml"
- "reqsign/**"
- "core/**"
- "context/**"
- "services/**"
pull_request:
branches:
- main
paths:
- ".asf.yaml"
- "website/**"
- ".github/workflows/website.yml"
- "Cargo.toml"
- "reqsign/**"
- "core/**"
- "context/**"
- "services/**"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# docusaurus.config.js resolves the released version from Git tags.
fetch-depth: 0

- uses: actions/setup-node@v6
with:
node-version: 24

- name: Enable pnpm
run: corepack enable

- name: Install dependencies
working-directory: website
run: pnpm install --frozen-lockfile

- name: Compile website examples
run: cargo check -p reqsign --examples --all-features

- name: Validate provider catalog against cargo metadata
working-directory: website
run: node scripts/validate-providers.mjs

- name: Build (fails on broken internal links)
working-directory: website
run: pnpm build

- name: Check for third-party runtime assets
working-directory: website
run: node scripts/check-external-assets.mjs

- name: Include ASF publishing configuration
run: cp .asf.yaml website/build/.asf.yaml

- name: Upload website
uses: actions/upload-artifact@v7.0.1
with:
name: website
path: website/build/
include-hidden-files: true
if-no-files-found: error

deploy:
needs: build
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download validated website
uses: actions/download-artifact@v8.0.1
with:
name: website
path: website/build

- name: Publish to ASF
uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: asf-site
publish_dir: website/build
# Keep the publication history so an earlier artifact can be recovered.
enable_jekyll: false
2 changes: 2 additions & 0 deletions licenserc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ builtin = "Apache-2.0-ASF"

[files]
includes = ["**/*.rs", "**/*.yml", "**/*.yaml", "**/*.toml"]
# Generated files cannot carry license headers.
excludes = ["website/pnpm-lock.yaml"]
23 changes: 23 additions & 0 deletions reqsign/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,26 @@ required-features = ["azure", "default-context"]
[[example]]
name = "google"
required-features = ["google", "default-context"]

[[example]]
name = "static_credentials"
required-features = ["aws", "default-context"]

[[example]]
name = "presign"
required-features = ["aws", "default-context"]

[[example]]
name = "custom_context"
required-features = ["aws", "default-context"]

[[example]]
name = "s3_express_grant"
required-features = ["aws", "default-context"]

[[example]]
name = "s3_express_sign"
required-features = ["aws", "default-context"]

[[example]]
name = "custom_http"
7 changes: 4 additions & 3 deletions reqsign/examples/aws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
// under the License.

use anyhow::Result;
use reqsign::aws;

#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();

// ANCHOR: quickstart
use reqsign::aws;
// Create a default signer for S3 in us-east-1
let signer = aws::default_signer("s3", "us-east-1");

Expand All @@ -37,6 +36,8 @@ async fn main() -> Result<()> {
// Sign the request
signer.sign(&mut req, None).await?;

// ANCHOR_END: quickstart

// Execute the request would require rebuilding with body
// In real usage, you'd use your HTTP client here
println!("Request signed successfully!");
Expand Down
7 changes: 4 additions & 3 deletions reqsign/examples/azure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
// under the License.

use anyhow::Result;
use reqsign::azure;

#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();

// ANCHOR: quickstart
use reqsign::azure;
// Create a default signer for Azure Storage
let signer = azure::default_signer();

Expand All @@ -37,6 +36,8 @@ async fn main() -> Result<()> {
// Sign the request
signer.sign(&mut req, None).await?;

// ANCHOR_END: quickstart

// Execute the request would require rebuilding with body
// In real usage, you'd use your HTTP client here
println!("Request signed successfully!");
Expand Down
35 changes: 35 additions & 0 deletions reqsign/examples/custom_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use reqsign::aws::{DefaultCredentialProvider, RequestSigner};
use reqsign::{Context, OsEnv, Signer};
use reqsign_command_execute_tokio::TokioCommandExecute;
use reqsign_file_read_tokio::TokioFileRead;
use reqsign_http_send_reqwest::ReqwestHttpSend;

fn main() {
let ctx = Context::new()
.with_file_read(TokioFileRead)
.with_http_send(ReqwestHttpSend::default())
.with_env(OsEnv)
.with_command_execute(TokioCommandExecute);
let _signer = Signer::new(
ctx,
DefaultCredentialProvider::new(),
RequestSigner::new("s3", "us-east-1"),
);
}
34 changes: 34 additions & 0 deletions reqsign/examples/custom_http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use bytes::Bytes;
use reqsign::{Context, HttpSend, Result};

// Implement this adapter over your own transport, such as browser fetch().
#[derive(Debug)]
struct MyHttpSend;

impl HttpSend for MyHttpSend {
async fn http_send(&self, _req: http::Request<Bytes>) -> Result<http::Response<Bytes>> {
todo!("drive the request through your own transport")
}
}

fn main() {
// This example only assembles the context; implement http_send before use.
let _ctx = Context::new().with_http_send(MyHttpSend);
}
7 changes: 4 additions & 3 deletions reqsign/examples/google.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
// under the License.

use anyhow::Result;
use reqsign::google;

#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();

// ANCHOR: quickstart
use reqsign::google;
// Create a default signer for Google Cloud Storage
let signer = google::default_signer("storage.googleapis.com");

Expand All @@ -37,6 +36,8 @@ async fn main() -> Result<()> {
// Sign the request
signer.sign(&mut req, None).await?;

// ANCHOR_END: quickstart

// Execute the request would require rebuilding with body
// In real usage, you'd use your HTTP client here
println!("Request signed successfully!");
Expand Down
34 changes: 34 additions & 0 deletions reqsign/examples/presign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use reqsign::aws;
use std::time::Duration;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let signer = aws::default_signer("s3", "us-east-1");
let mut req = http::Request::get("https://s3.amazonaws.com/my-bucket/report.csv")
.body(())?
.into_parts()
.0;
signer
.sign(&mut req, Some(Duration::from_secs(3600)))
.await?;
// Share req.uri over a trusted channel; it contains authentication material.
assert!(req.uri.query().is_some());
Ok(())
}
37 changes: 37 additions & 0 deletions reqsign/examples/s3_express_grant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use reqsign::aws::{
DefaultCredentialProvider, S3ExpressSessionConfig, S3ExpressSessionGrant,
S3ExpressSessionGranter, S3ExpressSessionMode,
};
use reqsign::{Granter, default_context};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = S3ExpressSessionConfig::from_bucket("my-bucket--usw2-az1--x-s3", "us-west-2")?;
let grant = S3ExpressSessionGrant::new(S3ExpressSessionMode::ReadOnly);
let granter = Granter::new(
default_context(),
DefaultCredentialProvider::new(),
S3ExpressSessionGranter::new(config, grant),
);
let scoped = granter.grant(None).await?;
// Keep the entire credential, including expires_in, when passing it on.
assert!(scoped.expires_in.is_some());
Ok(())
}
Loading
Loading