8000 Add `PUT /api/v1/trusted_publishing/tokens` API endpoint by Turbo87 · Pull Request #11131 · rust-lang/crates.io · GitHub
[go: up one dir, main page]

Skip to content

Add PUT /api/v1/trusted_publishing/tokens API endpoint #11131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
config: Add TRUSTPUB_AUDIENCE setting
This defaults to the domain name (crates.io / staging.crates.io) and controls the expected `aud` claim of the OIDC JWT in the Trusted Publishing token exchange.
  • Loading branch information
Turbo87 committed Jun 2, 2025
commit 03dd0684fa50f3fec0fcb8c08cac12f31b7dde5a
10 changes: 9 additions & 1 deletion src/config/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ pub struct Server {
pub html_render_cache_max_capacity: u64,

pub content_security_policy: Option<HeaderValue>,

/// The expected audience claim (`aud`) for the Trusted Publishing
/// token exchange.
pub trustpub_audience: String,
}

impl Server {
Expand Down Expand Up @@ -186,6 +190,9 @@ impl Server {
.unwrap_or_default()
);

let domain_name = dotenvy::var("DOMAIN_NAME").unwrap_or_else(|_| "crates.io".into());
let trustpub_audience = var("TRUSTPUB_AUDIENCE")?.unwrap_or_else(|| domain_name.clone());
Copy link
Member Author

Choose a reason for hiding this comment

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

this allows us to configure the expected aud claim, if necessary. it defaults to the domain name (crates.io / staging.crates.io).

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! This may or may not be applicable in your case, but noting: PyPI intentionally chose not to use the domain here, since we thought we might want to change the authentication and/or exchange subdomain at some point. So PyPI uses pypi and TestPyPI uses testpypi.

(This probably doesn't matter in practice, just flagging as a very small difference! In practice, any identifier that serves as a domain separator is fine, DNS name or whatever else 🙂)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, this reminds me that we might encounter a .io ccTLD issue in the future, even though we still have about 5 years left. It seems that not using the domain in the same way PyPI does makes some sense here, but I guess sticking with .io even if it gets removed probably won't be a big deal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, the potential .io transition would be a good reason to avoid using a DNS name as the "domain separator" here. But you're also 100% right that using aud: crates.io will keep on working just fine even if the Crates domain isn't that, since it's solely a mutually agreed audience of arbitrary structure 🙂

Copy link
Member Author
8000

Choose a reason for hiding this comment

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

aud: crates seems more confusing and unspecific to me than aud: crates.io. aud: crates-io has basically the same problem as aud: crates.io. since aud: crates.io would keep working even if we actually lost the ccTLD at some point I don't think it's worth introducing another name for it. if we had to migrate we could still allow both ccTLDs for the migration period.


Ok(Server {
db: DatabasePools::full_from_environment(&base)?,
storage,
Expand All @@ -210,7 +217,7 @@ impl Server {
page_offset_ua_blocklist,
page_offset_cidr_blocklist,
excluded_crate_names,
domain_name: dotenvy::var("DOMAIN_NAME").unwrap_or_else(|_| "crates.io".into()),
domain_name,
allowed_origins,
downloads_persist_interval: var_parsed("DOWNLOADS_PERSIST_INTERVAL_MS")?
.map(Duration::from_millis)
Expand All @@ -233,6 +240,7 @@ impl Server {
og_image_base_url: var_parsed("OG_IMAGE_BASE_URL")?,
html_render_cache_max_capacity: var_parsed("HTML_RENDER_CACHE_CAP")?.unwrap_or(1024),
content_security_policy: Some(content_security_policy.parse()?),
trustpub_audience,
})
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/tests/util/test_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crates_io_index::testing::UpstreamIndex;
use crates_io_index::{Credentials, RepositoryConfig};
use crates_io_team_repo::MockTeamRepo;
use crates_io_test_db::TestDatabase;
use crates_io_trustpub::github::test_helpers::AUDIENCE;
use crates_io_worker::Runner;
use diesel_async::AsyncPgConnection;
use futures_util::TryStreamExt;
Expand Down Expand Up @@ -491,6 +492,7 @@ fn simple_config() -> config::Server {
og_image_base_url: None,
html_render_cache_max_capacity: 1024,
content_security_policy: None,
trustpub_audience: AUDIENCE.to_string(),
}
}

Expand Down
0