Skip to content

Commit 7378247

Browse files
committed
Create "Trusted Publishing" database tables
1 parent f93958e commit 7378247

File tree

5 files changed

+160
-9
lines changed

5 files changed

+160
-9
lines changed

crates/crates_io_database/src/schema.patch

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
--- original
22
+++ patched
3-
@@ -21,9 +21,7 @@
3+
@@ -14,9 +14,7 @@
44
/// The `pg_catalog.tsvector` SQL type
55
///
66
/// (Automatically generated by Diesel.)
@@ -11,7 +11,7 @@
1111
}
1212

1313
diesel::table! {
14-
@@ -74,9 +72,9 @@
14+
@@ -67,9 +65,9 @@
1515
/// (Automatically generated by Diesel.)
1616
revoked -> Bool,
1717
/// NULL or an array of crate scope patterns (see RFC #2947)
@@ -23,7 +23,7 @@
2323
/// The `expired_at` column of the `api_tokens` table.
2424
///
2525
/// Its SQL type is `Nullable<Timestamptz>`.
26-
@@ -180,12 +178,6 @@
26+
@@ -175,12 +173,6 @@
2727
///
2828
/// (Automatically generated by Diesel.)
2929
created_at -> Timestamptz,
@@ -36,7 +36,7 @@
3636
}
3737
}
3838

39-
@@ -476,7 +468,7 @@
39+
@@ -483,7 +475,7 @@
4040
/// Its SQL type is `Array<Nullable<Text>>`.
4141
///
4242
/// (Automatically generated by Diesel.)
@@ -45,7 +45,7 @@
4545
/// The `target` column of the `dependencies` table.
4646
///
4747
/// Its SQL type is `Nullable<Varchar>`.
48-
@@ -703,6 +695,24 @@
48+
@@ -748,6 +740,24 @@
4949
}
5050

5151
diesel::table! {
@@ -70,7 +70,7 @@
7070
/// Representation of the `reserved_crate_names` table.
7171
///
7272
/// (Automatically generated by Diesel.)
73-
@@ -1018,7 +1028,8 @@
73+
@@ -1094,7 +1104,8 @@
7474
diesel::joinable!(crate_downloads -> crates (crate_id));
7575
diesel::joinable!(crate_owner_invitations -> crates (crate_id));
7676
diesel::joinable!(crate_owners -> crates (crate_id));
@@ -80,19 +80,19 @@
8080
diesel::joinable!(crates_categories -> categories (category_id));
8181
diesel::joinable!(crates_categories -> crates (crate_id));
8282
diesel::joinable!(crates_keywords -> crates (crate_id));
83-
@@ -1031,6 +1042,7 @@
83+
@@ -1112,6 +1123,7 @@
8484
diesel::joinable!(publish_limit_buckets -> users (user_id));
8585
diesel::joinable!(publish_rate_overrides -> users (user_id));
8686
diesel::joinable!(readme_renderings -> versions (version_id));
8787
+diesel::joinable!(recent_crate_downloads -> crates (crate_id));
8888
diesel::joinable!(version_downloads -> versions (version_id));
8989
diesel::joinable!(version_owner_actions -> api_tokens (api_token_id));
9090
diesel::joinable!(version_owner_actions -> users (user_id));
91-
@@ -1058,6 +1070,7 @@
91+
@@ -1143,6 +1155,7 @@
9292
publish_limit_buckets,
9393
publish_rate_overrides,
9494
readme_renderings,
9595
+ recent_crate_downloads,
9696
reserved_crate_names,
9797
teams,
98-
users,
98+
used_oidc_jti,

crates/crates_io_database/src/schema.rs

+57
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,28 @@ diesel::table! {
561561
}
562562
}
563563

564+
diesel::table! {
565+
/// Trusted Publisher OIDC configuration for GitHub Actions
566+
github_oidc_configs (id) {
567+
/// Unique identifier of the `github_oidc_configs` row
568+
id -> Int4,
569+
/// Unique identifier of the crate that this configuration is for
570+
crate_id -> Int4,
571+
/// GitHub user or organization that owns the repository
572+
repository_owner -> Varchar,
573+
/// Unique identifier of the user or organization that owns the repository
574+
repository_owner_id -> Int4,
575+
/// Name of the repository that this configuration is for
576+
repository_name -> Varchar,
577+
/// Name of the workflow file inside the repository that will be used to publish the crate
578+
workflow_filename -> Varchar,
579+
/// Optional publish environment that will be used to publish the crate
580+
environment -> Nullable<Varchar>,
581+
/// Date and time when the configuration was created
582+
created_at -> Timestamptz,
583+
}
584+
}
585+
564586
diesel::table! {
565587
/// Representation of the `keywords` table.
566588
///
@@ -607,6 +629,22 @@ diesel::table! {
607629
}
608630
}
609631

632+
diesel::table! {
633+
/// Temporary access tokens for OIDC-based publishing (aka. Trusted Publishing)
634+
oidc_tokens (id) {
635+
/// Unique identifier of the `oidc_tokens` row
636+
id -> Int8,
637+
/// Unique identifier of the crate that can be published using this token
638+
crate_id -> Int4,
639+
/// SHA256 hash of the token that can be used to publish the crate
640+
hashed_token -> Bytea,
641+
/// Date and time when the token was created
642+
created_at -> Timestamptz,
643+
/// Date and time when the token will expire
644+
expires_at -> Timestamptz,
645+
}
646+
}
647+
610648
diesel::table! {
611649
/// List of all processed CDN log files, used to avoid processing the same file multiple times.
612650
processed_log_files (path) {
@@ -765,6 +803,20 @@ diesel::table! {
765803
}
766804
}
767805

806+
diesel::table! {
807+
/// Used OIDC JWT IDs to prevent token reuse
808+
used_oidc_jti (id) {
809+
/// Unique identifier of the `used_oidc_jti` row
810+
id -> Int8,
811+
/// JWT ID from the OIDC token
812+
jti -> Varchar,
813+
/// Date and time when the JWT was used
814+
used_at -> Timestamptz,
815+
/// Date and time when the JWT would expire
816+
expires_at -> Timestamptz,
817+
}
818+
}
819+
768820
diesel::table! {
769821
/// Representation of the `users` table.
770822
///
@@ -1066,6 +1118,8 @@ diesel::joinable!(dependencies -> versions (version_id));
10661118
diesel::joinable!(emails -> users (user_id));
10671119
diesel::joinable!(follows -> crates (crate_id));
10681120
diesel::joinable!(follows -> users (user_id));
1121+
diesel::joinable!(github_oidc_configs -> crates (crate_id));
1122+
diesel::joinable!(oidc_tokens -> crates (crate_id));
10691123
diesel::joinable!(publish_limit_buckets -> users (user_id));
10701124
diesel::joinable!(publish_rate_overrides -> users (user_id));
10711125
diesel::joinable!(readme_renderings -> versions (version_id));
@@ -1093,15 +1147,18 @@ diesel::allow_tables_to_appear_in_same_query!(
10931147
dependencies,
10941148
emails,
10951149
follows,
1150+
github_oidc_configs,
10961151
keywords,
10971152
metadata,
1153+
oidc_tokens,
10981154
processed_log_files,
10991155
publish_limit_buckets,
11001156
publish_rate_overrides,
11011157
readme_renderings,
11021158
recent_crate_downloads,
11031159
reserved_crate_names,
11041160
teams,
1161+
used_oidc_jti,
11051162
users,
11061163
version_downloads,
11071164
version_owner_actions,

crates/crates_io_database_dump/src/dump-db.toml

+27
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ token_generated_at = "private"
148148
user_id = "private"
149149
crate_id = "private"
150150

151+
[github_oidc_configs]
152+
dependencies = ["crates"]
153+
[github_oidc_configs.columns]
154+
id = "private"
155+
crate_id = "private"
156+
repository_owner = "private"
157+
repository_owner_id = "private"
158+
repository_name = "private"
159+
workflow_filename = "private"
160+
environment = "private"
161+
created_at = "private"
162+
151163
[keywords.columns]
152164
id = "public"
153165
keyword = "public"
@@ -157,6 +169,15 @@ created_at = "public"
157169
[metadata.columns]
158170
total_downloads = "public"
159171

172+
[oidc_tokens]
173+
dependencies = ["crates"]
174+
[oidc_tokens.columns]
175+
id = "private"
176+
crate_id = "private"
177+
hashed_token = "private"
178+
created_at = "private"
179+
expires_at = "private"
180+
160181
[processed_log_files.columns]
161182
path = "private"
162183
time = "private"
@@ -209,6 +230,12 @@ publish_notifications = "private"
209230
[users.column_defaults]
210231
gh_access_token = "''"
211232

233+
[used_oidc_jti.columns]
234+
id = "private"
235+
jti = "private"
236+
used_at = "private"
237+
expires_at = "private"
238+
212239
[version_downloads]
213240
dependencies = ["versions"]
214241
[version_downloads.columns]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
drop table github_oidc_configs;
2+
drop table oidc_tokens;
3+
drop table used_oidc_jti;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
create table github_oidc_configs
2+
(
3+
id serial primary key,
4+
created_at timestamptz not null default now(),
5+
crate_id int not null references crates on delete cascade,
6+
repository_owner varchar not null,
7+
repository_owner_id int not null,
8+
repository_name varchar not null,
9+
workflow_filename varchar not null,
10+
environment varchar
11+
);
12+
13+
comment on table github_oidc_configs is 'Trusted Publisher OIDC configuration for GitHub Actions';
14+
comment on column github_oidc_configs.id is 'Unique identifier of the `github_oidc_configs` row';
15+
comment on column github_oidc_configs.created_at is 'Date and time when the configuration was created';
16+
comment on column github_oidc_configs.crate_id is 'Unique identifier of the crate that this configuration is for';
17+
comment on column github_oidc_configs.repository_owner is 'GitHub name of the user or organization that owns the repository';
18+
comment on column github_oidc_configs.repository_owner_id is 'GitHub ID of the user or organization that owns the repository';
19+
comment on column github_oidc_configs.repository_name is 'Name of the repository that this configuration is for';
20+
comment on column github_oidc_configs.workflow_filename is 'Name of the workflow file inside the repository that will be used to publish the crate';
21+
comment on column github_oidc_configs.environment is 'GitHub Actions environment that will be used to publish the crate (if `NULL` the environment is unrestricted)';
22+
23+
create index github_oidc_configs_repository_owner_id_repository_name_index
24+
on github_oidc_configs (repository_owner_id, repository_name);
25+
26+
-------------------------------------------------------------------------------
27+
28+
create table oidc_tokens
29+
(
30+
id bigserial primary key,
31+
created_at timestamptz not null default now(),
32+
crate_id int not null references crates on delete cascade,
33+
hashed_token bytea not null,
34+
expires_at timestamptz not null
35+
);
36+
37+
comment on table oidc_tokens is 'Temporary access tokens for OIDC-based publishing (aka. Trusted Publishing)';
38+
comment on column oidc_tokens.id is 'Unique identifier of the `oidc_tokens` row';
39+
comment on column oidc_tokens.created_at is 'Date and time when the token was created';
40+
comment on column oidc_tokens.crate_id is 'Unique identifier of the crate that can be published using this token';
41+
comment on column oidc_tokens.hashed_token is 'SHA256 hash of the token that can be used to publish the crate';
42+
comment on column oidc_tokens.expires_at is 'Date and time when the token will expire';
43+
44+
create unique index oidc_tokens_crate_id_hashed_token_uindex
45+
on oidc_tokens (crate_id, hashed_token);
46+
47+
-------------------------------------------------------------------------------
48+
49+
create table used_oidc_jti
50+
(
51+
id bigserial primary key,
52+
jti varchar not null,
53+
used_at timestamptz not null default now(),
54+
expires_at timestamptz not null
55+
);
56+
57+
comment on table used_oidc_jti is 'Used OIDC JWT IDs to prevent token reuse';
58+
comment on column used_oidc_jti.id is 'Unique identifier of the `used_oidc_jti` row';
59+
comment on column used_oidc_jti.jti is 'JWT ID from the OIDC token';
60+
comment on column used_oidc_jti.used_at is 'Date and time when the JWT was used';
61+
comment on column used_oidc_jti.expires_at is 'Date and time when the JWT would expire';
62+
63+
create unique index used_oidc_jti_jti_uindex
64+
on used_oidc_jti (jti);

0 commit comments

Comments
 (0)