Gitea SSL com Apache como proxy reverso

Para usar o container registry no k8s, é necessário utilizá-lo por meio de SSL.

Conteúdo da página

Queremos hospedar um registro de containers amigável e seguro - para enviar imagens Docker para lá e nosso cluster Kubernetes irá buscá-las desse registro. Assim surgiu a ideia de usar o Gitea sobre SSL.

Parte de Ferramentas para Desenvolvedores: O Guia Completo para Fluxos de Trabalho de Desenvolvimento Moderno

  1. Gitea já possui registro de containers
  2. Apache como proxy terminador TLS adicionará HTTPS ao nosso Gitea.
  3. Foi assim que começou… CA rotativa, certificados autoassinados…

Todo registro tem seus próprios segredos

Quando precisamos do registro no k8s

Infelizmente, o registro no cluster Kubernetes criado pelo kubespray não funciona para mim.

  • para empurrar para dentro dele, precisamos criar um túnel temporário via kube-proxy
  • após empurrar para dentro dele, minha versão atual do novo cluster não consegue puxar imagens deste registro interno

Depois de passar dois noites incríveis tentando corrigi-lo, decidi simplesmente usar o registro de containers interno do Gitea, apenas precisando configurar o acesso HTTPS a ele.

Vou torná-lo público de qualquer forma, para que o Docker e o k8s não tenham que fazer nenhum login no Docker. Talvez. Vamos ver como vai.

Testando se está funcionando

Para testar se o registro de containers nos serve, queremos ser capazes

  • de empurrar uma imagem para lá e
  • de criar uma implantação no k8s a partir dessa imagem
sudo docker pull alpine:3.12.0
sudo docker images
sudo docker tag a24bb4013296 localhost:5000/rg/alpine:version.3.12.0
sudo docker push localhost:5000/rg/alpine:version.3.12.0

Agora xed alp1.yaml ou nano alp1.yaml, dependendo do seu humor, e

apiVersion: apps/v1
kind: Deployment
metadata:
  name: alp-registry-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: alp-registry-test
  template:
    metadata:
      labels:
        app: alp-registry-test
    spec:
      containers:
        - name: alpine-test
          image: localhost:5000/rg/lpine:version.3.12.0
      imagePullSecrets:
      - name: registry-secret

Aqui está este arquivo disponível para download Depois, criando essa implantação

kubectl create -f alp1.yaml
kubectl get pods

kubectl describe po alp-registry-test-5f5cb94b97-njsp2
# ou o pod que foi criado, ou não foi criado

Sim, eu sei sobre esta parte

      imagePullSecrets:
      - name: registry-secret 

registry-secret é o nome do segredo criado pelo kubespray.

Limpeza

kubectl delete -f alp1.yaml

Como

Um conjunto de documentação está disponível no site do Gitea: https-setup

E nessa página: https://docs.gitea.com/administration/reverse-proxies

Passo 1 - Instalar Apache e criar um site de teste simples

Instalar Apache

sudo apt install apache2

Verificar o que temos no firewall

sudo ufw status

Se o firewall estiver ativo, pense em qual porta você deseja expor via HTTPS e permita-a. As configurações padrão do Apache são

sudo ufw app list

Podemos ver algo como

Aplicações disponíveis:
  Apache
  Apache Full
  Apache Secure
  OpenSSH

e para habilitar apenas a porta 443, executamos

sudo ufw allow 'Apache Secure'

ok. agora verifique o status do serviço

sudo systemctl status apache2

Próximo - criar um servidor virtual simples para testar o Apache

sudo mkdir /var/www/reg.homelab
sudo chown -R $USER:$USER /var/www/reg.homelab
sudo chmod -R 755 /var/www/reg.homelab
sudo nano /var/www/reg.homelab/index.html

Coloque lá

<html>
    <head>
        <title>Bem-vindo ao reg.homelab!</title>
    </head>
    <body>
        <h1>Sucesso! O host virtual reg.homelab está funcionando!</h1>
    </body>
</html>

depois

sudo nano /etc/apache2/sites-available/reg.homelab.conf

e coloque lá

<VirtualHost *:3080>
    ServerAdmin webmaster@localhost
    ServerName reg.homelab
    ServerAlias www.reg.homelab
    DocumentRoot /var/www/reg.homelab
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

depois desabilite o site padrão, habilite este e verifique como estamos indo

sudo a2ensite reg.homelab.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest

vejam algo como isso?

AH00558: apache2: Não foi possível determinar de forma confiável o nome de domínio totalmente qualificado do servidor, usando 127.0.1.1. Defina a diretiva 'ServerName' globalmente para suprimir esta mensagem

depois

sudo nano /etc/apache2/apache2.conf

adicione no final:

ServerName reg.homelab

E isso ainda não é o fim! agora precisamos remover a tentativa de vinculação da porta 80

sudo nano /etc/apache2/ports.conf

coloque lá

Listen 3030
...
Listen 443

E agora

sudo systemctl restart apache2
sudo systemctl status apache2
journalctl -xeu apache2.service
curl localhost:3080

OK! Agora navegue para <seu-endereço-ip-do-servidor>:3080

Passo 2 - Convertendo este site em um proxy reverso inseguro :) para o Gitea

sudo nano /etc/apache2/sites-available/reg.homelab.conf

colocando lá

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName reg.homelab
    ServerAlias www.reg.homelab
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    ProxyPreserveHost On
    ProxyRequests off
    AllowEncodedSlashes NoDecode
    ProxyPass / http://localhost:3000/ nocanon
</VirtualHost>

Faça algum teste de configuração

sudo apache2ctl configtest

Adicione alguns módulos do Apache e reinicie o Apache

sudo a2enmod proxy proxy_http ssl
sudo systemctl restart apache2
sudo systemctl status apache2

OK, agora navegue para ou curl

# Sim, ainda é um http, mas na porta 443
curl http://localhost:443
http://<Endereço_IP_Do_Servidor>:443/

Passo 3 - CA raiz autoassinada e certificado do site

SweetHome-RootCA.

CANAME=MostImportant-RootCA

# opcional, crie um diretório
mkdir $CANAME
cd $CANAME

# gerar chave privada criptografada com aes
openssl genrsa -aes256 -out $CANAME.key 4096

# criar certificado, 1826 dias = 5 anos
openssl req -x509 -new -nodes -key $CANAME.key -sha256 -days 1826 -out $CANAME.crt -subj '/CN=My Root CA/C=AT/ST=Vienna/L=Vienna/O=MyOrganisation'

# criar certificado para serviço
MYCERT=reg.homelab
openssl req -new -nodes -out $MYCERT.csr -newkey rsa:4096 -keyout $MYCERT.key -subj '/CN=My Firewall/C=AT/ST=Vienna/L=Vienna/O=MyOrganisation'

# criar um arquivo ext v3 para propriedades SAN
cat > $MYCERT.v3.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = reg.homelablab
DNS.2 = gitea.homelablab
IP.1 = 192.168.0.10
IP.2 = 192.168.0.11
EOF

openssl x509 -req -in $MYCERT.csr -CA $CANAME.crt -CAkey $CANAME.key -CAcreateserial -out $MYCERT.crt -days 730 -sha256 -extfile $MYCERT.v3.ext
Nas máquinas que se conectam ao gitea / registro

Registrar certificado raiz no linux:

sudo cp MostImportant-RootCA.crt /usr/local/share/ca-certificates
sudo update-ca-certificates

Registrar certificado raiz no windows:

  • Clique duas vezes no arquivo MostImportant-RootCA.crt
  • Importar para o usuário local
  • Selecione Truster Root CA.
  • Quando solicitado sobre importar certificado não confiável - clique em sim

Quando o git pull no windows diz sobre

Unable to resolve "unable to get local issuer certificate...

você pode dizer ao git para usar a camada de rede do windows por

git config --global http.sslbackend schannel

Passo 4 - Protegendo proxy com certificado autoassinado

https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html

Crie um certificado autoassinado SE você não o fez no passo 3

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -subj "/CN=reg.homelab" \
  -addext "subjectAltName = DNS:reg.homelab" \
  -keyout /etc/ssl/private/apache-selfsigned-reg.homelab.key \
  -out /etc/ssl/certs/apache-selfsigned-reg.homelab.crt

Ou apenas pegue do passo anterior

sudo cp reg.homelab.crt /etc/ssl/certs/apache-selfsigned-reg.homelab.crt
sudo cp reg.homelab.key /etc/ssl/private/apache-selfsigned-reg.homelab.key

Novamente, abra a configuração do host virtual

sudo nano /etc/apache2/sites-available/reg.homelab.conf

Adicione lá, no final, a seção SSL com os certificados

<VirtualHost *:443>
   ServerAdmin webmaster@localhost
   ServerName reg.homelab
   ServerAlias www.reg.homelab
   ErrorLog ${APACHE_LOG_DIR}/error.log
   CustomLog ${APACHE_LOG_DIR}/access.log combined
   ProxyPreserveHost On
   ProxyRequests off
   AllowEncodedSlashes NoDecode
   ProxyPass / http://localhost:3000/ nocanon
    
   SSLEngine on
   SSLCertificateFile /etc/ssl/certs/apache-selfsigned-reg.homelab.crt
   SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned-reg.homelab.key
</VirtualHost>

Verifique a configuração, reinicie o servidor, verifique o status e navegue para o nosso Gitea sobre SSL

sudo apache2ctl configtest
sudo systemctl restart apache2
sudo systemctl status apache2

# vá para: http://<Endereço_IP_Do_Servidor>:443/
# ou
curl -k -v https://localhost

o navegador alertará sobre o certificado autoassinado

Sua conexão não é privada
Atacantes podem estar tentando roubar suas informações de reg.homelab (por exemplo, senhas, mensagens ou cartões de crédito). Saiba mais
NET::ERR_CERT_AUTHORITY_INVALID

Mas vamos ignorá-lo, por enquanto, até usarmos o Let’s Encrypt.

Nota: Uma vez que sua configuração SSL do Gitea estiver funcionando, considere fazer backup do seu servidor. Veja Backup e Restauração do Servidor Gitea para instruções detalhadas.

Agora teste k8s

Faça algum DNSing…

Em cada nó k8s:

sudo nano /etc/hosts

e adicione lá

192.168.18.200 gitea.homelab
192.168.18.200 reg.homelab

CA Raiz

Em cada nó k8s:

sudo cp SweetHome-RootCA.crt /usr/local/share/ca-certificates
sudo update-ca-certificates

E reinicie agora

Criar segredo com credenciais do registro

https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

sudo docker login reg.homelab
kubectl create secret generic regcred --from-file=.dockerconfigjson=/home/rg/.docker/config.json --type=kubernetes.io/dockerconfigjson

ou

kubectl create secret docker-registry regcred --docker-server=your-registry-server --docker-username=your-name --docker-password=your-pword --docker-email=your-email

Nova imagem docker e implantação k8s

sudo docker pull alpine:3.12.0
sudo docker images
sudo docker tag a24bb4013296 reg.homelab/rg/alpine:version.3.12.0
sudo docker push reg.homelab/rg/alpine:version.3.12.0

Agora nano alp2.yaml, o arquivo está [disponível]avaliable

apiVersion: apps/v1
kind: Deployment
metadata:
  name: alp-registry-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: alp-registry-test
  template:
    metadata:
      labels:
        app: alp-registry-test
    spec:
      containers:
        - name: alpine-test
          image: reg.homelab/rg/alpine:version.3.12.0
      imagePullSecrets:
      - name: regcred

Aqui está este arquivo disponível para download: Depois, criando essa implantação

kubectl create -f alp2.yaml
kubectl get pods
kubectl describe po alp...

Limpeza

kubectl delete -f alp2.yaml