@@ -29,51 +29,115 @@ keyring.
29
29
30
30
Suppose a user has their authentication token stored in a password manager, and
31
31
the password manager provides a command, ` /usr/bin/cargo-creds ` , to decrypt and
32
- print that token in a secure way. Instead of also storing the token in
33
- plaintext, the user can add this snippet to their own ` .cargo/credentials ` to
34
- authenticate with crates.io:
32
+ print that token in a secure way. Instead of storing the token in plaintext,
33
+ the user can add this snippet to their own Cargo config to authenticate with
34
+ crates.io:
35
35
36
36
``` toml
37
37
[registry ]
38
- token-from -process = " /usr/bin/cargo-creds"
38
+ credential -process = " /usr/bin/cargo-creds"
39
39
```
40
40
41
- When authentication is required Cargo will execute the command and use its
42
- output as the token, which will never be stored by Cargo on disk. If the
43
- command requires arguments, for example ` password-manager creds crates-io ` , you
44
- can add them in a list:
41
+ When authentication is required, Cargo will execute the command to acquire the
42
+ token, which will never be stored by Cargo on disk.
43
+
44
+ It will be possible to use ` credential-process ` on both crates.io and alternative
45
+ registries.
46
+
47
+ # Reference-level explanation
48
+ [ reference-level-explanation ] : #reference-level-explanation
49
+
50
+ A new key, ` credential-process ` , will be added to the ` [registry] ` and
51
+ ` [registries.NAME] ` sections of the configuration file. When a ` token ` key is
52
+ also present, the latter will take precedence over ` credential-process ` to
53
+ maintain backward compatibility, and a warning will be issued to let the user
54
+ know about that.
55
+
56
+ The ` registry.credential-process ` value will be used for all registries. If a
57
+ specific registry specifies the value in the ` registries ` table, then that
58
+ will take precedence.
59
+
60
+ The ` credential-process ` key accepts either a string containing the executable
61
+ and arguments or an array containing the executable name and the arguments.
62
+ This follows Cargo's convention for executables defined in config.
63
+
64
+ There are special strings in the ` credential-process ` that Cargo will replace
65
+ with a given value:
66
+
67
+ * ` {name} ` — Name of the registry.
68
+ * ` {api_url} ` — The API URL.
69
+ * ` {action} ` — The authentication action (described below).
45
70
46
71
``` toml
47
72
[registry ]
48
- token-from-process = [" password-manager" , " creds" , " crates-io" ]
73
+ credential-process = ' cargo osxkeychain {action}'
74
+
75
+ [registries .my-registry ]
76
+ credential-process = [' /path/to/myscript' , ' {name}' ]
49
77
```
50
78
51
- It will be possible to use ` token-from-process ` on both crates.io and
52
- alternative registries.
79
+ There are two different kinds of token processes that Cargo supports. The
80
+ simple "basic" kind will only be called by Cargo when it needs a token. This
81
+ is intended for simple and easy integration with password managers, that can
82
+ often use pre-existing tooling. The more advanced "Cargo" kind supports
83
+ different actions passed as a command-line argument. This is intended for more
84
+ pleasant integration experience, at the expense of requiring a Cargo-specific
85
+ process to glue to the password manager. Cargo will determine which kind is
86
+ supported by the ` credential-process ` definition. If it contains the
87
+ ` {action} ` argument, then it uses the advanced style, otherwise it assumes it
88
+ only supports the "basic" kind.
53
89
54
- # Reference-level explanation
55
- [ reference-level-explanation ] : #reference-level-explanation
90
+ ## Basic authenticator
91
+
92
+ A basic authenticator is a process that returns a token on stdout. Newlines
93
+ will be trimmed. The process inherits the user's stdin and stderr. It should
94
+ exit 0 on success, and nonzero on error.
95
+
96
+ With this form, ` cargo login ` and ` cargo logout ` are not supported and return
97
+ an error if used.
98
+
99
+ ## Cargo authenticator
56
100
57
- A new key, ` token-from-process ` , will be added to the ` [registry] ` and
58
- ` [registries.NAME] ` sections of the ` .cargo/credentials ` configuration file.
59
- When a ` token ` key is also present, the latter will take precedence over
60
- ` token-from-process ` to maintain backward compatibility, and a warning will be
61
- issued to let the user know about that.
101
+ The protocol between the Cargo and the process is very basic, intended to
102
+ ensure the credential process is kept as simple as possible. Cargo will
103
+ execute the process with the ` {action} ` argument indicating which action to
104
+ perform:
62
105
63
- The ` token-from-process ` key accepts either a string containing the binary to
64
- call or a list containing the binary name and the arguments to provide to it.
106
+ * ` store ` — Store the given token in secure storage.
107
+ * ` get ` — Get a token from storage.
108
+ * ` erase ` — Remove a token from storage.
65
109
66
- When a ` cargo ` subcommand needs the authentication token, Cargo will execute
67
- the binary contained in the configuration key with the defined arguments (if
68
- provided by the user). The process will inherit Cargo's standard input and
69
- error, and the standard output will be captured by Cargo to read the token
70
- (with trimmed newlines). If the command returns an exit code other than ` 0 `
71
- Cargo will treat that as a failure.
110
+ The ` cargo login ` command will use ` store ` to save a token. Commands that
111
+ require authentication, like ` cargo publish ` , will use ` get ` to retrieve a
112
+ token. A new command, ` cargo logout ` will be added which will use the ` erase `
113
+ command to remove a token.
114
+
115
+ The process inherits the user's stderr, so the process can display messages.
116
+ Some values are passed in via environment variables (see below). The expected
117
+ interactions are:
118
+
119
+ * ` store ` — The token is sent to the process's stdin, terminated by a newline.
120
+ The process should store the token keyed off the registry name. If the
121
+ process fails, it should exit with a nonzero exit status.
122
+
123
+ * ` get ` — The process should send the token to its stdout (trailing newline
124
+ will be trimmed). The process inherits the user's stdin, should it need to
125
+ receive input.
126
+
127
+ If the process is unable to fulfill the request, it should exit with a
128
+ nonzero exit code.
129
+
130
+ * ` erase ` — The process should remove the token associated with the registry
131
+ name. If the token is not found, the process should exit with a 0 exit
132
+ status.
133
+
134
+ ## Environment
72
135
73
136
The following environment variables will be provided to the executed command:
74
137
75
- * ` CARGO ` - Path to the ` cargo ` binary executing the command.
76
- * ` CARGO_REGISTRY_NAME ` - Name of the registry the authentication token is for.
138
+ * ` CARGO ` — Path to the ` cargo ` binary executing the command.
139
+ * ` CARGO_REGISTRY_NAME ` — Name of the registry the authentication token is for.
140
+ * ` CARGO_REGISTRY_API_URL ` — The URL of the registry API.
77
141
78
142
# Drawbacks
79
143
[ drawbacks ] : #drawbacks
@@ -87,37 +151,28 @@ The solution proposed by this RFC isn't tied to any secret storage services and
87
151
can be adapted to work with virtually any secret storage the user might rely
88
152
on, while being relatively easy to understand and use.
89
153
90
- An alternative with better user experience but more limited customization would
91
- be for Cargo to provide cross platform, native integration with the most
92
- popular secret storages, for example the system keyring:
93
-
94
- ``` toml
95
- [registry ]
96
- token-from-system-keyring = true
97
- ```
98
-
99
- The issue with the native integration proposal is it helps only a subset of
100
- users, and it requires Cargo to implement and test integrations with each
101
- secret storage we expect a lot of users to use.
102
-
103
154
# Prior art
104
155
[ prior-art ] : #prior-art
105
156
106
157
Multiple command line tools implement this system or a similar one to retrieve
107
158
authentication tokens or other secrets:
108
159
109
- * [ awscli] [ awscli ] includes the ` credentials_process ` setting with nearly the
110
- same behavior as the one proposed in this RFC.
160
+ * [ awscli] [ awscli ] includes the ` credentials_process ` setting which calls
161
+ a process with arguments provided by the user. The process is expected to
162
+ emit JSON that contains the access key.
111
163
* [ Docker CLI] [ docker ] offers "credential stores", programs the Docker CLI
112
164
calls with specific arguments expecting JSON output. Implementations are
113
165
provided for common storage systems, and the protocol is documented for users
114
166
who want to integrate with their custom system.
115
167
* [ Ansible Vault] [ ansible ] allows to specify an executable file as the
116
168
decryption password, executing it when needed.
169
+ * [ Git] has a credential mechanism using store/get/erase arguments, and
170
+ ` key=value ` parameters send and received with the process.
117
171
118
172
[ awscli ] : https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sourcing-external.html
119
173
[ docker ] : https://docs.docker.com/engine/reference/commandline/login/#credentials-store
120
174
[ ansible ] : https://docs.ansible.com/ansible/latest/user_guide/vault.html#providing-vault-passwords
175
+ [ git ] : https://git-scm.com/docs/gitcredentials#_custom_helpers
121
176
122
177
# Unresolved questions
123
178
[ unresolved-questions ] : #unresolved-questions
@@ -127,15 +182,14 @@ authentication tokens or other secrets:
127
182
# Future possibilities
128
183
[ future-possibilities ] : #future-possibilities
129
184
130
- To allow for a better user experience for users of popular secret storages the
131
- community could create Cargo plugins that easily integrate with such systems.
132
- For example, an hypothetical Cargo plugin to integrate with the system keyring
133
- could allow users to add this configuration snippet:
185
+ To allow for a better user experience for users of popular secret storages,
186
+ Cargo can provide built-in support for common systems. It is proposed that a
187
+ ` credential-process ` with a ` cargo: ` prefix will use some internal support. For
188
+ example, ` credential-process = 'cargo:system-keychain' ` .
134
189
135
- ``` toml
136
- [registry ]
137
- token-from-process = " cargo credentials-system-keyring"
138
- ```
190
+ Additionally, the community could create Cargo plugins that implement
191
+ different storage systems. For example, a hypothetical Cargo plugin could be
192
+ specified as ` credential-process = 'cargo credential-1password {action}' ` .
139
193
140
194
Encrypting the stored tokens or alternate authentication methods are out of the
141
195
scope of this RFC, but could be proposed in the future to provide additional
0 commit comments