]>
git.proxmox.com Git - rustc.git/blob - src/tools/cargo/src/cargo/util/auth/asymmetric.rs
1 //! Registry asymmetric authentication support. See [RFC 3231] for more.
3 //! [RFC 3231]: https://rust-lang.github.io/rfcs/3231-cargo-asymmetric-tokens.html
5 use pasetors
::keys
::AsymmetricPublicKey
;
6 use pasetors
::keys
::AsymmetricSecretKey
;
8 use pasetors
::paserk
::FormatAsPaserk
;
9 use pasetors
::version3
;
10 use pasetors
::version3
::PublicToken
;
11 use time
::format_description
::well_known
::Rfc3339
;
12 use time
::OffsetDateTime
;
14 use crate::core
::SourceId
;
15 use crate::ops
::RegistryCredentialConfig
;
16 use crate::CargoResult
;
21 /// The main body of an asymmetric token as describe in RFC 3231.
22 #[derive(serde::Serialize)]
25 #[serde(skip_serializing_if = "Option::is_none")]
27 #[serde(skip_serializing_if = "Option::is_none")]
28 mutation
: Option
<&'a
str>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 name
: Option
<&'a
str>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 vers
: Option
<&'a
str>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 cksum
: Option
<&'a
str>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 challenge
: Option
<&'a
str>,
37 /// This field is not yet used. This field can be set to a value >1 to
38 /// indicate a breaking change in the token format.
39 #[serde(skip_serializing_if = "Option::is_none")]
43 /// The footer of an asymmetric token as describe in RFC 3231.
44 #[derive(serde::Serialize)]
50 /// Checks that a secret key is valid, and returns the associated public key in
52 pub fn paserk_public_from_paserk_secret(secret_key
: Secret
<&str>) -> Option
<String
> {
53 let secret
: Secret
<AsymmetricSecretKey
<version3
::V3
>> =
54 secret_key
.map(|key
| key
.try_into()).transpose().ok()?
;
55 let public
: AsymmetricPublicKey
<version3
::V3
> = secret
57 .map(|key
| key
.try_into())
61 let mut paserk_pub_key
= String
::new();
62 FormatAsPaserk
::fmt(&public
, &mut paserk_pub_key
).unwrap();
66 /// Generates a public token from a registry's `credential` configuration for
67 /// authenticating to a `source_id`
69 /// An optional `mutation` for authenticating a mutation operation aganist the
71 pub fn public_token_from_credential(
72 credential
: RegistryCredentialConfig
,
74 mutation
: Option
<&'_ Mutation
<'_
>>,
75 ) -> CargoResult
<Secret
<String
>> {
76 let RegistryCredentialConfig
::AsymmetricKey((secret_key
, secret_key_subject
)) = credential
else {
77 anyhow
::bail
!("credential must be an asymmetric secret key")
80 let secret
: Secret
<AsymmetricSecretKey
<version3
::V3
>> =
81 secret_key
.map(|key
| key
.as_str().try_into()).transpose()?
;
82 let public
: AsymmetricPublicKey
<version3
::V3
> = secret
84 .map(|key
| key
.try_into())
87 let kip
= (&public
).try_into()?
;
88 let iat
= OffsetDateTime
::now_utc();
90 let message
= Message
{
91 iat
: &iat
.format(&Rfc3339
)?
,
92 sub
: secret_key_subject
.as_deref(),
93 mutation
: mutation
.and_then(|m
| {
95 Mutation
::PrePublish
=> return None
,
96 Mutation
::Publish { .. }
=> "publish",
97 Mutation
::Yank { .. }
=> "yank",
98 Mutation
::Unyank { .. }
=> "unyank",
99 Mutation
::Owners { .. }
=> "owners",
102 name
: mutation
.and_then(|m
| {
104 Mutation
::PrePublish
=> return None
,
105 Mutation
::Publish { name, .. }
106 | Mutation
::Yank { name, .. }
107 | Mutation
::Unyank { name, .. }
108 | Mutation
::Owners { name, .. }
=> *name
,
111 vers
: mutation
.and_then(|m
| {
113 Mutation
::PrePublish
| Mutation
::Owners { .. }
=> return None
,
114 Mutation
::Publish { vers, .. }
115 | Mutation
::Yank { vers, .. }
116 | Mutation
::Unyank { vers, .. }
=> *vers
,
119 cksum
: mutation
.and_then(|m
| {
122 | Mutation
::Yank { .. }
123 | Mutation
::Unyank { .. }
124 | Mutation
::Owners { .. }
=> return None
,
125 Mutation
::Publish { cksum, .. }
=> *cksum
,
128 challenge
: None
, // todo: PASETO with challenges
132 let footer
= Footer
{
133 url
: &source_id
.url().to_string(),
141 serde_json
::to_string(&message
)
142 .expect("cannot serialize")
145 serde_json
::to_string(&footer
)
146 .expect("cannot serialize")