Categorias
Desenvolvimento Web Programação Tutoriais

Git + GPG = Assinando suas contribuições

Recentemente o core do PHP passou por uma situação, no mínimo, inusitada: 2 commits foram feitos em nome de personalidades da comunidade. Isso é possível porque quando registramos uma alteração no git através de um commit, ele registra os dados que queremos que sejam registrados, incluindo o usuário e email que você disse ter (git config user.name "Cauan" e git config user.email "cauan@dominio.com"). Veja que você não precisa validar email nem nada.

Aplicações que hospedam projetos em git geralmente pedem pra gente validar o email usado nos commits, assim são capazes de inferir que aquele código enviado é de quem disse ter enviado. Mas é apenas uma associação “lógica”. O commit diz que foi feito por fulana, e a fulana é uma usuária válida aqui no Github/Gitlab, então vou exibir a foto e nome dessa fulana aqui na interface.

Se o git não garante que quem fez uma alteração é quem diz ser, como a gente pode garantir? Assinando nossas mudanças com uma chave criptográfica.

Felizmente o git permite que a gente especifique uma chave privada configurada no GPG e cuida de todo o processo de assinar nossas mudanças. Na outra ponta, nós compartilhamos a chave pública com o Github/Gitlab para que valide o commit assinado e então possam garantir que aquele código foi feito por quem diz ter feito.

O pessoal do PHP preparou um guia bem completo sobre como configurar o GPG e git para que o incidente não se repita. Vou colocar aqui o resumo do resumo para quem tiver alguma dificuldade com inglês, mas se tiver alguma dúvida, pode usar os comentários.

Atenção: todos os comando devem ser executados com seu usuário normal. Quando necessário, o sudo vai estar explicitado.

O símbolo $ não faz parte do comando, é só pra diferenciar o que é um comando e o que é uma saída de comando. Sempre que tiver o $, você pode copiar o que está na frente e executar no seu terminal.

Primeiro, instale o GPG:

SistemaComando(s)
macOS com Homebrewbrew install gpg
Ubuntu, Debian, Mint, Kalisudo apt install gnupg
CentOS, Fedora, RHELsudo yum install gnupg

Se você usa Zsh como shell, você precisa configurar um tty para que funcione corretamente os comandos interativos com o GPG:

$ mkdir "${HOME}"/.gnupg
$ chmod 700 "${HOME}"/.gnupg
$ >> "${HOME}"/.zshrc echo 'GPG_TTY="$(tty)" && export GPG_TTY || echo "Could not determine TTY: $?" >&2'
$ source "${HOME}"/.zshrc

Verificando que a instalação funcionou:

$ gpg --version | head -2
gpg (GnuPG) 2.2.21
libgcrypt 1.8.6
$ gpg-connect-agent /bye && echo 'GPG ok' || echo 'ERROR: GPG not running'
GPG ok
$ [ -r "${GPG_TTY}" ] && echo 'TTY ok' || echo 'ERROR: TTY not found'
TTY ok

Agora vamos gerar sua chave de assinatura GPG. É imprescindível escolher uma senha forte para proteger sua chave:

$ gpg --batch --generate-key <(echo '
Key-Type: RSA
Key-Length: 4096
Expire-Date: 0
Name-Real: Fulana de Tal
Name-Email: fulana@dominio.com.br
')

Precisamos descobrir a versão curta do ID da chave gerada:

$ gpg -K --keyid-format SHORT
sec   rsa4096/02783663 2020-08-26 [SCEA]
      79694216A0DECA5B53E94E96910A1F8402783663
uid         [ultimate] Fulana de Tal <fulana@dominio.com.br>

Repare no resultado do comando anterior a primeira linha. O que vem após rsa4096/ é o ID que nós queremos, nesse exemplo: 02783663.

Vamos deixar esse valor em uma variável de ambiente para facilitar o restante das configurações, basta executar:

$ export GPG_KEYID=02783663

Estamos terminando, precisamos dizer ao git para usar essa chave para assinar nossas alterações no repositório:

$ git config --global --replace user.signingkey "${GPG_KEYID}"
$ git config --global --replace commit.gpgsign true
$ git config --global --replace tag.gpgsign true

Por último, precisamos informar ao Github/Gitlab nossa chave, para que ele possa verificar o autor das mudanças:

$ gpg --armor --export "${GPG_KEYID}" | pbcopy

pbcopy é um comando do macOS para jogar informação na área de transferência (equivalente a um Ctrl+C). Substitua essa parte pelo comando equivalente no seu ambiente se for outro, ou simplesmente retire o trecho | pbcopy e a chave será exibe no terminal, daí basta selecionar e copiar.

Com a chave copiada, acesse suas configurações:

Feito isso, todos os seus novos commits deve ser assinados e se tudo ocorreu bem, aparecerão como verificados nos Git da vida:

Imagem com uma lista de commits contendo o selo "verified" do Github

Atualizado em 13/04/2021: eu segui esses passos do artigo original em um macOS sem o gpg previamente instalado e com o git relativamente atualizado. Caso seu ambiente já tenha gpg ou a versão do git seja muito antiga, verifique a seguinte resposta no StackOverflow. Agradecimento ao Elton Minetto pela dica nos comentários.

Atualizado em 01/05/2021: como alertou nos comentários o Adjamilton, depois da gente atualizar o conteúdo do arquivo .zshrc precisamos recarregar seus valores usando o comando source "${HOME}"/.zshrc para que as mudanças surtam efeito. O trecho já está atualizado.

Categorias
CakePHP PHP Programação

Obrigado pelos peixes SVN

Há alguns anos descobri o fantástico mundo do controle de versão, naquele momento me perguntei “como vivi sem isso até hoje?”. Dali em diante podia alterar arquivos sem medo, qualquer erro era só voltar uma versão e tudo certo. Trabalhar em equipe finalmente se tornava algo fácil, graças ao Subversion – SVN.

Porém os anos passaram e algumas coisas começaram a fazer falta: como faço quando estou desenvolvendo algo grande, fico sem commitar até ter algo estável/usável? crio um branch para isso? mas e depois para unir os branches, e os conflitos? além disso, se só eu estou trabalhando em cima disso, porque commitar para todo mundo algo não pronto?

Foi aí que descobri o GIT, um sistema de controle de versão distribuído, open source e gratuito. Ok, ele é gratuito e open source, mas isso não é motivo suficiente. Como disse, ele é um sistema de controle de versão distribuído, isso quer dizer que cada um que tem uma cópia do repositório tem de fato uma cópia dele, e pode servir outras pessoas, ver histórico, tudo localmente.

Então de quebra, ele resolve o problema de ter de criar um branch para desenvolver uma funcionalidade que só eu vou mexer, posso controlar cada alteração minha localmente, e quando quiser – se quiser – posso sincronizar meu repositório local com um outro central (que eu considero central, já que essa figura não existe no GIT). E mais, ele é MUITO RÁPIDO. Acho que para ajudar na argumentação de que é rápido basta dizer que ele foi feito por alguns desenvolvedores do Kernel Linux, e gerencia todo o código trabalhado por eles – e não é pouca coisa.

Ainda estou caminhando com o GIT, tenho aproveitado minha ânsia de aprende-lo junto com a de contribuir com softwares open source para criar e disponibilizar projetos no GitHub.

A grande maioria dos projetos é voltado ao CakePHP, mas há outras coisas também. Alguns projetos que podem interessar são:

  • Comitiva – Sistema construído em CakePHP 1.3 para gerenciamento de eventos;
  • Plugin Mailer – Um plugin que ajuda na utilização da biblioteca PHP SwiftMailer dentro do CakePHP;
  • Behavior Locale – Um behavior para transformar dados vindo do usuário de seu padrão local para um padrão internacional (de banco de dados)
  • Libs – uma coleção de pequenos scripts PHP que fui fazendo ao longo da vida. Há coisas boas, coisas úteis, coisas não tão úteis, mas tudo pode ser usado ao menos como ponto inicial para uma implementação mais elaborada.