Para acceder a repositorios en CodeCommit a través de git, se requiere configurar git para que utilice el comando de consola de AWS como “ayudante de autenticación”, es decir, que “aws” genere un usuario/clave al vuelo que pueda utilizar git para la operación contra el repositorio.
Es muy común que intentando descargar repositorios desde AWS con Git nos topemos con el siguiente mensaje error:
fatal: unable to access 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio/': The requested URL returned error: 403
Veamos a continuación como solucionar este problema y configurar correctamente nuestro entorno para usar AWS Codecommit con Git.
Paso 1 – Obtener las credenciales
Opción 1: desde la consola AWS, IAM user, obtener aws_access_key_id, aws_secret_acces_key. Más información AQUI.
Opción 2: usar el plugin de chrome SAML to AWS STS Key para descargar la llave que se genera para el navegador cuando se hace login.
Paso 2 – Incluir las credenciales en el archivo de credenciales de AWS
El archivo ~/.aws/credentials contiene las credenciales AWS presentes en la cuenta local. Ahí crear una sección con un nombre que identifique al perfil:
[mi-perfil] aws_access_key_id = ASIASP6... aws_secret_access_key = Kb5ufJqwJ1t….. aws_session_token = FwoGZXIvYXdzECcaD…...
Se puede validar el acceso correcto listando los repositorios con el siguiente comando. Reemplazar la región (us-east-1 en este ejemplo) por la que corresponda.
aws --profile mi-perfil --region us-east-1 codecommit list-repositories
Resultado:
{ "repositories": [ { "repositoryName": "mi-repositorio", "repositoryId": "aaaaa-bbbb-cccc-dddd-eeeeeeeee" }, (...) ] }
Paso 3 – Configurar el uso del perfil para acceder a los repositorios AWS
Se debe indicar a GIT que se quiere utilizar un “credential helper” para acceder a los repositorios de AWS Codecommit, pero que no esté disponible para el resto, de lo contrario no podríamos acceder correctamente a Github o repos privados.
Para personalizar que repositorios usarán que credential helper, editamos el archivo de configuración git global del usuario ~/.gitconfig. Agregamos las siguientes líneas para los repos AWS Codecommit que se estén usando. Si se tiene más de una región, hay que agregar una sección por cada una.
[credential "https://git-codecommit.us-east-1.amazonaws.com"] helper = !aws --profile mi-perfil codecommit credential-helper $@ UseHttpPath = true
Aquí se indica que para los repositorios de la región us-east-1 se utilice el perfil mi-perfil de la configuración de llaves AWS.
Con esto podemos realizar operaciones contra el repo Codecommit a través de Git, por ejemplo un clone:
git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio
Niveles de configuración GIT – Problemas para configurar credential helper
Git tiene varios niveles de configuración que se sobreponen para armar el conjunto de parámetros que se utilizando en cada ejecución. Según la documentación, la precedencia de las configuraciones va desde lo más general hasta lo particular:
1. Nivel “system” – Todo el sistema operativo
Linux: /etc/gitconfig
OSX: /Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig
2. Nivel “global” (usuario)
~/.gitconfig
3. Nivel “local” (repositorio)
.git/config
Así, se pueden definir configuraciones generales a nivel sistema o para el usuario, a la vez que se personalizan otras para un repositorio en particular.
Para listar las configuraciones vigentes de git, se puede usar el siguiente comando dentro de un repositorio local para que muestra cada parámetro y el archivo de origen desde donde lo obtiene.
jmakuc$ git config --show-origin -l file:/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig credential.helper=osxkeychain file:/Users/jmakuc/.gitconfig core.excludesfile=/Users/jmakuc/.gitignore_global file:/Users/jmakuc/.gitconfig user.name=Jonathan Makuc file:/Users/jmakuc/.gitconfig user.email=jmakuc@bithaus.cl file:/Users/jmakuc/.gitconfig commit.template=/Users/jmakuc/.stCommitMsg file:/Users/jmakuc/.gitconfig credential.https://git-codecommit.us-east-1.amazonaws.com.helper=!aws --profile mi-perfil codecommit credential-helper $@ file:/Users/jmakuc/.gitconfig credential.https://git-codecommit.us-east-1.amazonaws.com.usehttppath=true file:.git/config core.repositoryformatversion=0 file:.git/config core.filemode=true file:.git/config core.bare=false file:.git/config core.logallrefupdates=true file:.git/config core.ignorecase=true file:.git/config core.precomposeunicode=true file:.git/config remote.origin.url=https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* file:.git/config branch.development.remote=origin file:.git/config branch.development.merge=refs/heads/development
Aquí podemos ver que hay 2 archivos origen desde donde se define el parámetro “credential.helper”. El primero es el nivel sistema que indica el keychain de OSX. El segundo a nivel “global” del usuario, que indica al comando AWS como proveedor de autenticación.
En mi caso, Git no quiso tomar la configuración global (usuario) para sobreescribir el valor de sistema, por tanto las operaciones contra el repositorio AWS fallaban.
Para detectar el problema, es útil activar el “trace” de Git a través del siguiente comando:
export GIT_TRACE=1
Con esto, se puede ver que aunque la configuración global (usuario) tiene un credential helper, el comando está tomando la configuración de sistema.
jmakuc$ git fetch 10:51:43.335023 git.c:340 trace: built-in: git 'fetch' 10:51:43.337159 run-command.c:626 trace: run_command: 'git-remote-https' 'origin' 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio' 10:51:43.996457 run-command.c:626 trace: run_command: 'git credential-osxkeychain get' 10:51:44.003678 git.c:572 trace: exec: 'git-credential-osxkeychain' 'get' 10:51:44.004250 run-command.c:626 trace: run_command: 'git-credential-osxkeychain' 'get' fatal: unable to access 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio/': The requested URL returned error: 403
Si bien se puede editar el archivo nivel sistema y quitar la configuración que usa el Keychain, es poco conveniente para el resto de los repositorios que se tengan en el ambiente. Es mejor deshabilitar el uso de la configuración nivel sistema para esta sesión de terminal:
export GIT_CONFIG_NOSYSTEM=1
Así, la configuración que muestra Git solo tiene los parámetros “global” (usuario) y “local”:
jmakuc$ git config --show-origin -l file:/Users/jmakuc/.gitconfig core.excludesfile=/Users/jmakuc/.gitignore_global file:/Users/jmakuc/.gitconfig user.name=Jonathan Makuc file:/Users/jmakuc/.gitconfig user.email=jmakuc@bithaus.cl file:/Users/jmakuc/.gitconfig commit.template=/Users/jmakuc/.stCommitMsg file:/Users/jmakuc/.gitconfig credential.https://git-codecommit.us-east-1.amazonaws.com.helper=!aws --profile mi-perfil codecommit credential-helper $@ file:/Users/jmakuc/.gitconfig credential.https://git-codecommit.us-east-1.amazonaws.com.usehttppath=truefile:.git/config core.repositoryformatversion=0 file:.git/config core.filemode=true file:.git/config core.bare=false file:.git/config core.logallrefupdates=true file:.git/config core.ignorecase=true file:.git/config core.precomposeunicode=true file:.git/config remote.origin.url=https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* file:.git/config branch.development.remote=origin file:.git/config branch.development.merge=refs/heads/development
Finalmente, el comando Git funciona! 😀
jmakuc$ git fetch 11:18:49.014356 git.c:340 trace: built-in: git 'fetch' 11:18:49.039127 run-command.c:626 trace: run_command: 'git-remote-https' 'origin' 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/mi-repositorio' 11:18:49.763053 run-command.c:626 trace: run_command: 'aws codecommit credential-helper $@ get' 11:18:51.022539 run-command.c:626 trace: run_command: 'aws codecommit credential-helper $@ store' 11:18:51.596029 run-command.c:626 trace: run_command: 'aws codecommit credential-helper $@ store' 11:18:52.164858 run-command.c:626 trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all' '--quiet' 11:18:52.185185 run-command.c:626 trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all' '--quiet' 11:18:52.188531 git.c:340 trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all' '--quiet' 11:18:52.200980 run-command.c:1452 run_processes_parallel: preparing to run up to 1 tasks 11:18:52.201074 run-command.c:1484 run_processes_parallel: done 11:18:52.201234 run-command.c:626 trace: run_command: 'gc' '--auto' 11:18:52.206087 git.c:340 trace: built-in: git 'gc' '--auto'
No es tan complicado cuando sabemos como funciona 🙂
Enjoy!