Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
171 changes: 87 additions & 84 deletions book/07-git-tools/sections/credentials.asc
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
[[_credential_caching]]
=== Credential Storage
=== Almacenamiento de credenciales

(((credentials)))
(((git commands, credential)))
If you use the SSH transport for connecting to remotes, it's possible for you to have a key without a passphrase, which allows you to securely transfer data without typing in your username and password.
However, this isn't possible with the HTTP protocols – every connection needs a username and password.
This gets even harder for systems with two-factor authentication, where the token you use for a password is randomly generated and unpronounceable.

Fortunately, Git has a credentials system that can help with this.
Git has a few options provided in the box:

* The default is not to cache at all.
Every connection will prompt you for your username and password.
* The ``cache'' mode keeps credentials in memory for a certain period of time.
None of the passwords are ever stored on disk, and they are purged from the cache after 15 minutes.
* The ``store'' mode saves the credentials to a plain-text file on disk, and they never expire.
This means that until you change your password for the Git host, you won't ever have to type in your credentials again.
The downside of this approach is that your passwords are stored in cleartext in a plain file in your home directory.
* If you're using a Mac, Git comes with an ``osxkeychain'' mode, which caches credentials in the secure keychain that's attached to your system account.
This method stores the credentials on disk, and they never expire, but they're encrypted with the same system that stores HTTPS certificates and Safari auto-fills.
* If you're using Windows, you can install a helper called ``winstore.''
This is similar to the ``osxkeychain'' helper described above, but uses the Windows Credential Store to control sensitive information.
It can be found at https://gitcredentialstore.codeplex.com[].

You can choose one of these methods by setting a Git configuration value:
Si usa protocolo SSH para conectar a los remotos, es posible tener una llave sin clave, lo que permite
tranferir la data sin tener que escribir el nombre de usuario y la clave cada vez.
Sin embargo, esto no es posible por el protocolo HTTP - cada conexión necesita usuario y contraseña.
Esto se vuelve incluso más complicado para sistemas con autenticación de dos pasos, donde el token que
se usa para la clave es generado al azar y no puede ser utilizado.

Afortunadamente, Git tiene un sistema de credenciales que lo ayuda con esto.
Git tiene las siguientes funciones disponibles:

* El default es no guardar cache para nada.
Cada conexión solicitará el usuario y contraseña.
* El modo ``cache'' mantiene las credenciales en memoria por un cierto periodo de tiempo.
Ninguna de las claves es guardada en disco, y son borradas del cache tras 15 minutos.
* El modo ``store'' guarda las credenciales en un archivo de texto plano en disco, y nunca expiran.
Esto quiere decir que hasta que se cambie la contraseña en el host Git, no se necesitarán escribir credenciales de nuevo.
La desventaja de este método es que sus claves son guardadas en texto plano en un archivo dentro de su máquina.
* Si está usando Mac, Git viene con el modo ``osxkeychain'', el cual guarda en cache las credenciales en el llavero que está conectado a su cuenta de sistema.
Este método guarda las claves en disco, y nunca expiran, pero están encriptadas con el mismo sistema que guarda los certificados HTTPS y los auto-completar de Safari.
* Si está en Windows, puede installer un ayudante llamado ``winstore.''
Este es similar al ayudante de ``osxkeychain'' descrito arriba, pero usa Windows Credential Store para controlar la información sensible.
Se puede encontrar en https://gitcredentialstore.codeplex.com[].

Se puede elegir cualquiera de estos métodos mediante el valor de configuración de Git:

[source,console]
----
$ git config --global credential.helper cache
----

Some of these helpers have options.
The ``store'' helper can take a `--file <path>` argument, which customizes where the plaintext file is saved (the default is `~/.git-credentials`).
The ``cache'' helper accepts the `--timeout <seconds>` option, which changes the amount of time its daemon is kept running (the default is ``900'', or 15 minutes).
Here's an example of how you'd configure the ``store'' helper with a custom file name:
Algunos de estos ayudantes tienen opciones.
El modo ``store'' puede tomar un argumento `--file <ruta>', el cual personaliza la ubicación final del archivo en texto plano (el default es `~/.git-credentials`).

El modo ``cache'' acepta la opción `--timeout <segundos>`, la cual cambia la cantidad de tiempo que el demonio se mantiene en ejecución (el default es ``900'', o 15 minutos).
Aquí hay un ejemplo de cómo configurar el modo ``store'' con un nombre de archivo personalizado:

[source,console]
----
$ git config --global credential.helper store --file ~/.my-credentials
----

Git even allows you to configure several helpers.
When looking for credentials for a particular host, Git will query them in order, and stop after the first answer is provided.
When saving credentials, Git will send the username and password to *all* of the helpers in the list, and they can choose what to do with them.
Here's what a `.gitconfig` would look like if you had a credentials file on a thumb drive, but wanted to use the in-memory cache to save some typing if the drive isn't plugged in:
Git incluso permite configurar varios modos.
Cuando se buscan por credenciales para un host en particular, Git las mostrará en orden, y se detendrá después que la primer respuesta sea entregada.
Cuando se guardan credenciales, Git mandará el usuario y contraseña a *todos* los modos en la lista, y se podrá elegir qué hacer con ellos.
Aquí se muestra cómo se vería un archivo `.gitconfig` si tuviera un archivo de credenciales en una memoria, pero quisiera usar lo almacenado en cache cuando la memoria no esté conectada:

[source,ini]
----
Expand All @@ -52,14 +55,14 @@ Here's what a `.gitconfig` would look like if you had a credentials file on a th
helper = cache --timeout 30000
----

==== Under the Hood
==== Bajo el sombrero

How does this all work?
Git's root command for the credential-helper system is `git credential`, which takes a command as an argument, and then more input through stdin.
¿Cómo funciona todo esto?
El comando raíz de Git para el asistente de credenciales es `git credential`, el cual toma un comando como argumento, y luego más inputs por medio de stdin.

This might be easier to understand with an example.
Let's say that a credential helper has been configured, and the helper has stored credentials for `mygithost`.
Here's a session that uses the ``fill'' command, which is invoked when Git is trying to find credentials for a host:
Esto podría ser más fácil de entender con un ejemplo.
Supongamos que un modo de credenciales ha sido configurado, y que el asistente a guardado credenciales para `mygithost`.
Aquí hay una sesión que usa el comando ``fill'', el cual es invocado cuando Git está intentando encontrar credenciales para el host:

[source,console]
----
Expand All @@ -83,15 +86,15 @@ username=bob
password=s3cre7
----

<1> This is the command line that initiates the interaction.
<2> Git-credential is then waiting for input on stdin.
We provide it with the things we know: the protocol and hostname.
<3> A blank line indicates that the input is complete, and the credential system should answer with what it knows.
<4> Git-credential then takes over, and writes to stdout with the bits of information it found.
<5> If credentials are not found, Git asks the user for the username and password, and provides them back to the invoking stdout (here they're attached to the same console).
<1> Esta es el comando que inicia la interacción.
<2> Git-credential entonces espera por un input en stdin.
Nosotros lo proveemos con lo que conocemos: el protocolo y el nombre de host.
<3> Una línea en blanco indica que el input está completo, y el sistema de credencial debería responder con lo que conoce.
<4> Git-credential entonces entra en acción, y escribe en stdout los bits de información que encontró.
<5> Si no se encuentran credenciales, Git pregunta al usuario por el usuario y la contraseña, y lo entrega de vuelta a stdout (aquí ya están conectados a la misma consola).

The credential system is actually invoking a program that's separate from Git itself; which one and how depends on the `credential.helper` configuration value.
There are several forms it can take:
El sistema de credenciales en realidad está invocando un programa que está separado de Git; el que figura en el valor de configuración `credential.helper`.
Hay varias formas que puede tomar:

[options="header"]
|======
Expand All @@ -102,20 +105,20 @@ There are several forms it can take:
| `!f() { echo "password=s3cre7"; }; f` | Code after `!` evaluated in shell
|======

So the helpers described above are actually named `git-credential-cache`, `git-credential-store`, and so on, and we can configure them to take command-line arguments.
The general form for this is ``git-credential-foo [args] <action>.''
The stdin/stdout protocol is the same as git-credential, but they use a slightly different set of actions:
Así, los modos descritos arriba en realidad se llaman `git-credential-cache`, `git-credential-store`, y en adelante, y los podemos configurar para que tomen argumentos de línea de comando.
La forma general para conseguirlo es ``git-credential-foo [args] <acción>.''
El protocolo stdin/stdout es el mismo que git-credential, pero usan un conjunto ligeramente distinto de acciones:

* `get` is a request for a username/password pair.
* `store` is a request to save a set of credentials in this helper's memory.
* `erase` purge the credentials for the given properties from this helper's memory.
* `get` es una petición para un par usuario/contraseña.
* `store` es una petición para guardar un grupo de credenciales en la memoria del modo.
* `erase` purga las credenciales para las propiedades entregadas de la memoria del modo.

For the `store` and `erase` actions, no response is required (Git ignores it anyway).
For the `get` action, however, Git is very interested in what the helper has to say.
If the helper doesn't know anything useful, it can simply exit with no output, but if it does know, it should augment the provided information with the information it has stored.
The output is treated like a series of assignment statements; anything provided will replace what Git already knows.
Para las acciones `store` y `erase`, no es necesaria una respuesta (Git la ignora de todos modos).
Para la acción `get`, sin embargo, Git está muy interesado en lo que el modo tiene que decir.
Si el modo no sabe nada útil, puede simplemente salir sin mostrar inforamción, pero si sabe algo, debería aumentar la información provista con la información que ha almacenado.
El output es tratado como una serie de declaraciones de assignación; nada provista remplazará lo que Git ya conoce.

Here's the same example from above, but skipping git-credential and going straight for git-credential-store:
Aquí hay un ejemplo de lo explicado, pero saltando git-credential y yendo directo a git-credential-store:

[source,console]
----
Expand All @@ -132,51 +135,51 @@ username=bob <3>
password=s3cre7
----

<1> Here we tell `git-credential-store` to save some credentials: the username ``bob'' and the password ``s3cre7'' are to be used when `https://mygithost` is accessed.
<2> Now we'll retrieve those credentials.
We provide the parts of the connection we already know (`https://mygithost`), and an empty line.
<3> `git-credential-store` replies with the username and password we stored above.
<1> Aquí decimos con `git-credential-store` que guarde las credenciales: username ``bob'' y la clave ``s3cre7'' serán usadas cuando se accese a `https://mygithost`.
<2> Ahora vamos a recibir las credenciales.
Ahora proveemos las partes de la conexión que ya conocemos (`https://mygithost`), y una línea en blanco.
<3> `git-credential-store` responde con el usuario y la contraseña que guardamos al comienzo.

Here's what the `~/git.store` file looks like:
Aquí se muestra cómo se vería `~/git.store`:

[source]
----
https://bob:s3cre7@mygithost
----

It's just a series of lines, each of which contains a credential-decorated URL.
The `osxkeychain` and `winstore` helpers use the native format of their backing stores, while `cache` uses its own in-memory format (which no other process can read).
Es solamente una serie de líneas, cada una conteniendo una URL con credenciales.
Los modos `osxkeychain` y `winsoter` usan el formato nativo de sus almacenamientos, mientras `cache` usa su propio formato en memoria (el cual no puede ser leído por ningún proceso).

==== A Custom Credential Cache
==== Un cache de credenciales personalizado

Given that `git-credential-store` and friends are separate programs from Git, it's not much of a leap to realize that _any_ program can be a Git credential helper.
The helpers provided by Git cover many common use cases, but not all.
For example, let's say your team has some credentials that are shared with the entire team, perhaps for deployment.
These are stored in a shared directory, but you don't want to copy them to your own credential store, because they change often.
None of the existing helpers cover this case; let's see what it would take to write our own.
There are several key features this program needs to have:
Dado que `git-credential-store` y amigos son programas separados de Git, no es difícil de notar que _cualquier_ programa puede ser un asistente de credenciales de Git.
Los modos provistos por Git cubren muchos de los casos de uso, pero no todos.
Por ejemplo, supongamos que tu equipo tiene credenciales que son compartidas con el equipo entero, tal vez para despliegue.
Estas están guardadas en un directorio compartido, pero no deseas copiarlas a tu almacén de credenciales, porque cambian de manera seguida.
Ninguno de los modos existentes cubre este caso; veamos lo que tomaría para escribir tu propio modo.
Existen muchas funcionalidades clave que necesita tener este programa:

. The only action we need to pay attention to is `get`; `store` and `erase` are write operations, so we'll just exit cleanly when they're received.
. The file format of the shared-credential file is the same as that used by `git-credential-store`.
. The location of that file is fairly standard, but we should allow the user to pass a custom path just in case.
. La única acción que necesitamos vigilar es `get`; `store` y `erase` son operaciones de escritura, así que solo saldremos limpiamente cuando sean recibidas.
. El formato de archivo de la credencial compartida es el mismo que se usa por `git-credential-store`.
. La ubicación de ese archivo es relativamente estándar, pero deberías permitir al usuario entregar una ruta alterna por si acaso.

Once again, we'll write this extension in Ruby, but any language will work so long as Git can execute the finished product.
Here's the full source code of our new credential helper:
Una vez más, vamos a escribir esta extensión en Ruby, pero cualquier lenguaje funcionará siempre y cuando Git pueda ejecutar el producto final.
Aquí está el código de nuestro nuevo asistente de credenciales:

[source,ruby]
--------
include::../git-credential-read-only[]
--------

<1> Here we parse the command-line options, allowing the user to specify the input file. The default is `~/.git-credentials`.
<2> This program only responds if the action is `get` and the backing-store file exists.
<3> This loop reads from stdin until the first blank line is reached.
The inputs are stored in the `known` hash for later reference.
<4> This loop reads the contents of the storage file, looking for matches.
If the protocol and host from `known` match this line, the program prints the results to stdout and exits.
<1> Aquí analizamos las opciones de la línea de comando, permitiendo al usuario especificar un archivo. El default es `~/.git-credentials`.
<2> Este programa solo responde si la acción es `get` y el archivo de almacenamiento existe.
<3> Este bucle lee de stdin hasta que se encuentre la primer línea en blanco.
Los input son guardadoes en el hash `known` para una posterior referencia.
<4> Este bucle lee el contenido del archivo de almacenamiento, buscando por concordancias.
Si el protocolo y el host de `known` concuerdan con la línea, el programa imprime el resultado a stdout y sale.

We'll save our helper as `git-credential-read-only`, put it somewhere in our `PATH` and mark it executable.
Here's what an interactive session looks like:
Guardaremos nuestro modo como `git-credential-read-only`, ponlo en algún lugar en nuestro `PATH` y lo marcamos como ejecutable.
Aquí se muestra cómo se vería una sessión interactiva:

[source,console]
----
Expand All @@ -190,11 +193,11 @@ username=bob
password=s3cre7
----

Since its name starts with ``git-'', we can use the simple syntax for the configuration value:
Dado que su nombre comienza con ``git-'', podemos usar la sintaxis simple para el valor de configuración:

[source,console]
----
$ git config --global credential.helper read-only --file /mnt/shared/creds
----

As you can see, extending this system is pretty straightforward, and can solve some common problems for you and your team.
Como se puede apreciar, extender este sistema es bastante sencillo, y puede resolver algunos problemas comunes para usted y su equipo.
2 changes: 1 addition & 1 deletion status.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"1-git-tools.asc": 100,
"sections/advanced-merging.asc": 100,
"sections/bundling.asc": 0,
"sections/credentials.asc": 0,
"sections/credentials.asc": 100,
"sections/debugging.asc": 100,
"sections/interactive-staging.asc": 0,
"sections/replace.asc": 0,
Expand Down