1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
|
Authentication ring
===================
When accessing a remote branch (specified as an URL), it may occur that the
server requests an authentication.
This authentication can be provided in different ways:
1. Embedding the user and password
in the URL::
bzr branch <scheme>://<user>:<password>@host:port/path
* ``scheme``: Any transport protocol requiring authentication.
* ``user``: The login used to authenticate.
* ``password``: The associated password.
* ``host``: The address of the server.
* ``port``: The port the server is listening to.
* ``path``: The path on the server.
2. Embedding the user in the URL and let bzr find the right password or prompt
for one::
bzr branch <scheme>://<user>@host/path
3. Embedding nothing in the URL and let bzr find user and password or prompt
for user and/or password::
bzr branch <scheme>://host/path
This specification proposes a mechanism that will allow users to
just use ``bzr branch <scheme>://host/path`` or ``bzr branch
<scheme>://<user>@host/path`` and leaves bzr find the ``user``
and ``password`` in its configuration files.
When no user is specified for ``FTP``, ``SFTP`` or ``SSH``, the actual behavior
of ``bzr`` is to default to ``getpass.get_user()``.
Any implementation of this specification should respect that behaviour.
This specification also proposes a way to describe credentials so that several
remote branches can use the same definition. This is particularily important
for users handling a lot of passwords and who need to update them on a regular
basis.
Rationale
---------
Embedding user and passwords in the command line is a security
hazard (see `bug #34685
<https://launchpad.net/products/bzr/+bug/34685>`_).
Storing passwords in ``~/.config/breezy/breezy.conf`` or
``~/.config/breezy/locations.conf`` is also a security risk.
Typing user and passwords is error-prone and boring.
Yet, a safe way to store passwords, while allowing bzr to retrieve them, when
needed, could improve the bzr user experience.
This specification describes a way to provide user and passwords to bzr while
storing them in a relatively safe way.
Note that SSH servers can be configured to use keys instead of (``user``,
``password``) and, when used with appropriate agents, provide the same kind of
comfort this specification aims to provide for all other schemes. Since SSH
agents provide a safer way to secure the passwords, this specification is
restricted to providing ``user`` but does not provide ``password`` when used
for SSH.
Authentication definitions
--------------------------
There are two kinds of authentication used by the various schemes supported by
bzr:
1. user and password
``FTP`` and ``SFTP`` needs a (``user``, ``password``) to authenticate against a
``host`` (SFTP can use SSH keys too, but we don't talk about that in this
specification as SSH agents provide a better solution).
2. user, realm and password
``HTTP`` and ``HTTPS`` needs a (``user, realm, password``) to authenticate
against a host. But, by using ``.htaccess`` files, for example, it is possible
to define several (``user, realm, password``) for a given ``host``. So what is
really needed is (``user``, ``password``, ``host``, ``path``). The ``realm``
can be ignored [#ignored_realm]_ as long as it is still presented to the user
when prompting for the password (unless someone found a way to declare two
different realms for the same path).
``HTTP proxy`` can be handled as ``HTTP`` (or ``HTTPS``) by explicitly
specifying the appropriate port.
.. [#ignored_realm] The true purpose of realms is to allow the same credentials
to be reused for disjoint hierarchies. Ignoring them in this specification
aims to simplify the user experience while still allowing to share the same
credentials for a whole hierarchy.
To take all schemes into account, the password will be deduced from a set of
authentication definitions (``scheme``, ``host``, ``port``, ``path``, ``user``,
``password``).
* ``scheme``: can be empty (meaning the rest of the definition can be used
for any scheme), ``SFTP`` and ``bzr+ssh`` should not be used here, ``ssh``
should be used instead since this is the real scheme regarding
authentication,
* ``host``: can be empty (to act as a default for any host),
* ``port`` can be empty (useful when an host provides several servers for the
same scheme), only numerical values are allowed, this should be used only
when the server uses a port different than the scheme standard port,
* ``path``: can be empty (FTP or SFTP will never use it),
* ``user``: can be empty (``bzr`` will defaults to Python's
``getpass.get_user()`` for FTP, SFTP and SSH),
* ``password``: can be empty (for security reasons, a user may use the
definitions without storing the passwords but want to be prompted ; or the
password will be provided by an external plugin via the
``password_encoding`` mechanism decribed below). Must be left empty for
``ssh``.
* ``password_encoding``: can be empty (default is ``plaintext``).
Also note that an optional ``verify_certificates=no`` field will allow the
connection to ``HTTPS`` hosts that provides a self certified certificate (the
default should be to refuse the connection and inform the user). (Not
implemented yet)
Multiple definitions can be provided and, for a given URL, bzr will select a
(``user`` [, ``password``]) based on the following rules :
1. the first match wins,
2. empty fields match everything,
3. ``scheme`` matches even if decorators are used in the requested URL,
4. ``host`` matches exactly or act as a domain if it starts with '.'
(``project.bzr.sf.net`` will match ``.bzr.sf.net`` but ``projectbzr.sf.net``
will not match ``bzr.sf.net``).
5. ``port`` matches if included in the requested URL (exact matches only)
6. ``path`` matches if included in the requested URL (and by rule #2 above,
empty paths will match any provided path).
An optional ``password_encoding`` field may specify how the password is encoded
but has no impact on the definition selection.
Possible values are ``plaintext`` (no encoding at all) and ``base64``. When the
field is absent, ``plaintext`` is assumed. Additional encodings may be added in
future versions.
Encoding passwords in ``base64``, while weak, provides protection against
accidental reading (if an administrator have to look into the file, he will not
see the passwords in clear).
This specification intends to ease the authentication providing, not to secure
it in the best possible way.
Plugins can provide additional password encodings. The provided
``netrc_credential_store`` plugin can be used as an example implementation.
Future versions of this specification may provide additional
encodings [#password_encoding]_.
.. [#password_encoding] Additional password encoding methods may be defined
that will rely on external means to store the password which, in these
cases, will not appear anymore in the definition. It is assumed that
additional password encodings will provide a storage outside of the file
described here. The ``netrc`` encoding, for example, provides passwords by
retrieving them from the ``.netrc`` file.
File format
-----------
Even if ``~/.config/breezy/breezy.conf`` and
``~/.config/breezy/locations.conf`` seems to provide most of the needed
infrastructure, we choose to use a dedicated file
for the authentication info ``~/.config/breezy/authentication.conf`` for the following
reasons:
* allow the user to protect the content of one file only, relaxing security
constraints on the others,
* while ``locations.conf`` is organized around *local* branches,
``authentication.conf`` is organized around *remote* branches or more
generally servers. The same authentification definition can even be used
for several schemes for servers providing those schemes.
``~/.config/breezy//authentication.conf`` will use the same file format as
``~/.config/breezy/breezy.conf``.
Each section describes an authentication definition.
The section name is an arbitrary string, only the ``DEFAULT`` value is reserved
and should appear as the *last* section.
Each section should define:
* ``user``: the login to be used,
Each section could define:
* ``host``: the remote server,
* ``port``: the port the server is listening,
* ``verify_certificates``: to control certificate verification (useful
for self certified hosts). This applies to HTTPS only. Accepted values
are yes and no, default to yes.
* ``path``: the branch location,
* ``password``: the password,
* ``password_encoding``: the method used to encode the password if any,
The default content of the file will be::
[DEFAULT]
This section could define:
* ``user``: default user to be used (if not defined the usual
bzr way applies, see below).
* ``password_encoding``: default password encoding.
Use Cases
---------
The use cases described below use the file format defined above.
* all FTP connections to the foo.net domain are done with the same (``user``,
``password``)::
# Identity on foo.net
[foo.net]
scheme=ftp
host=foo.net
user=joe
password=secret-pass
will provide ('joe', 'secret-pass') for::
bzr branch ftp://foo.net/bzr/branch
bzr pull ftp://bzr.foo.net/bzr/product/branch/trunk
* all connections are done with the same ``user`` (the remote one for which
the default bzr one is not appropriate) and the password is always prompted
with some exceptions::
# Pet projects on hobby.net
[hobby]
host=r.hobby.net
user=jim
password=obvious1234
# Home server
[home]
scheme=https
host=home.net
user=joe
# Obtain the base64 encoded password by running 'echo -n "secret-pass" | base64'
password='c2VjcmV0LXBhc3M='
password_encoding=base64
verify_certificates=no # Still searching a free certificate provider
[DEFAULT]
# Our local user is barbaz, on all remote sites we're known as foobar
user=foobar
* an HTTP server and a proxy::
# development branches on dev server
[dev]
scheme=https
host=dev.company.com
path=/dev
user=user1
password=pass1
# toy branches
[localhost]
scheme=http
host=dev.company.com
path=/
user=user2
password=pass2
# proxy
[proxy]
scheme=http
host=proxy.company.com
port=3128
user=proxyuser1
password=proxypass1
* source hosting provider declaring sub-domains for each project::
[sfnet domain]
# we use SFTP, but SSH is the scheme used for authentication
scheme=ssh
# The leading '.' ensures that 'sf.net' alone doesn't match
host=.sf.net
user=georges
password=ben...son
UI Changes
----------
Depending on the info provided in the URL, bzr will interact with the user in
different ways:
1. ``user`` and ``password`` given in the URL.
Nothing to do.
2. ``user`` given in the URL.
Get a password from ``~/.config/breezy/authentication.conf`` or prompt
for one if none is found.
3. No ``user`` given in the URL (and no ``password``).
Get a user from ``~/.config/breezy/authentication.conf`` or prompt for one if
none is found. Continue as 2. (Not implemented yet)
Note: A user will be queried only if the server requires it for ``HTTP`` or
``HTTPS``, other protocols always require a user.
In any case, if the server refuses the authentication, bzr reports to the user
and terminates.
Implementation constraints
--------------------------
* bzr should be able to prompt for a ``user`` for a given (``scheme``, ``host``
[, ``realm``]). Note that ``realm`` is available only after a first
connection attempt to the server.
* No assumptions should be made about the clients of this service
(i.e. Transport is the primary target but plugins must be able to use it as
well, the definitions used: (``scheme, host, [port,] path``) are general
enough to described credentials for ``svn`` servers or LaunchPad XML-RPC
calls).
* Policies regarding default users may be taken into account by the
implementations, there is no good way to represent that in this specification
and stays flexible enough to accommodate various needs (default user policies
may differ for different schemes and that may be easier to handle in the code
than in the authentication file itself).
* If no user can be found by the mechanism described above, bzr should still
default to ``getpass.get_user()`` and may attempt a second matching to obtain
a password.
* As this specification proposes a matching between some credentials
definitions and real URLs, the implementation provides an optional UI
feedback about which credential definition is used. Using ``-Dauth`` will
output some traces in the ``brz.log`` file metionning the sections
used. This allows the user to validate his definitions.
Questions and Answers
---------------------
* What if a ``.authinfo`` file exists ?
* It will be ignored,
* Automatic (one-time) conversions may be proposed if sufficient demand
exists,
* What if a ``.netrc`` file exists ?
* It is honored if the definition specifies
``password_encoding=netrc``.
* What mode should the authentication file use ?
* 600 read/write for owner only by default, if another mode (more
permissive) is used, a warning will be issued to inform the users of the
potential risks.(Not implemented yet)
* What about using ``seahorse`` on Ubuntu or ``KeyChain Access`` on Mac OS X ?
* plugins can be written and registered to handle the associated
``password_encoding``.
* Could it be possible to encode the whole authentication file with an SSH key
?
* yes and if the user configure a ssh-agent it will not be queried for
pass-phrase every time we want to query the file for a password. But
that seems a bit extreme for a first version.(Not implemented yet and
may be never)
* Why can't bzr update the authentication file when it queried the user for a
password ?
* a future version may address that but:
1. The user may want to decide which passwords are stored in the file and
which aren't.
2. The user should decide if the passwords are encoded (and how) or not
(but we may default to base64).
3. The right definition may be hard to get right, but reducing it to
(``scheme, host, [port,] user, password``) may be a good start. I.e. no
path so that all paths on the host will match. The user will have to
modify it for more complex configurations anyway.
|