Gitea SSL com Apache como proxy reverso

Para usar o registro de contêiner no k8s, precisamos dele sobre ssl

Conteúdo da página

Queremos hospedar um registro de contêiner seguro e elegante — para empurrar imagens docker lá e nosso cluster kubernetes as puxar delas deste registro.
Assim surgiu a ideia de usar o gitea sobre ssl.

  1. Gitea já tem registro de contêiner
  2. O Apache como proxy de terminação TLS adicionará HTTPS ao nosso Gitea.
  3. Assim começou… CA rot, 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 ele, precisamos criar um túnel temporário via kube-proxy
  • depois de empurrar para ele, a minha versão atual do novo cluster não consegue puxar imagens desse registro interno

Depois de passar algumas noites incríveis tentando consertar isso,
decidi simplesmente usar o registro de contêiner interno do Gitea, basta configurar o acesso HTTPS a ele.

Vou torná-lo público de qualquer forma, então o docker e o k8s não precisam fazer nenhum login no docker.
Talvez. Vamos ver como vamos.

Testando se está funcionando

Para testar se o registro de contêiner nos serve, queremos ser capazes de

  • empurrar uma imagem lá e
  • criar um deployment 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
Então, criando este deployment

kubectl create -f alp1.yaml
kubectl get pods

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

Sim, eu sei sobre este trecho

      imagePullSecrets:
      - name: registry-secret 

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

Limpeza

kubectl delete -f alp1.yaml

Como

Uma série de documentação está disponível no site do Gitea: https-setup

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

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

Instalar o Apache

sudo apt install apache2

Verificar o que temos no firewall

sudo ufw status

Se o firewall estiver ativo, pense em qual porta você quer expor via https e permita-a.
Configurações padrão do apache são

sudo ufw app list

Podemos ver algo como

Available applications:
  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>

então

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>

então desative o site padrão, ative este e verifique como estamos

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

veja algo como isso?

AH00558: apache2: Não foi possível determinar com confiança o nome completo do servidor, usando 127.0.1.1. Defina a diretiva 'ServerName' globalmente para suprimir esta mensagem

então

sudo nano /etc/apache2/apache2.conf

adicione no final:

ServerName reg.homelab

E isto ainda não é o fim! agora precisamos remover o tentativa de vincular a porta 80

sudo nano /etc/apache2/ports.conf

coloque lá

Listen 3030
...
Listen 443

Agora

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

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

Passo 2 - Convertendo este site para 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 alguns testes 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 até ou curl

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

Passo 3 - Autoridade de Certificação Raiz autoassinada e certificado do site

SweetHome-RootCA.

CANAME=MostImportant-RootCA

# opcional, criar 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 o 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 v3 ext para propriedades de 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
Em máquinas conectando-se ao gitea / registro

Registre o certificado raiz no linux:

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

Registre o certificado raiz no windows:

  • Clique duas vezes no arquivo MostImportant-RootCA.crt
  • Importe para o usuário local
  • Selecione Autoridade de Certificação Raiz Confiançável.
  • Quando solicitado sobre importar certificado não confiável — clique sim

Quando o git pull no windows disser sobre

Não é possível resolver "unable to get local issuer certificate...

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

git config --global http.sslbackend schannel

Passo 4 - Protegendo o proxy com certificado autoassinado

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

Crie um certificado autoassinado SE não criou 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 dele 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 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 até o Gitea sobre SSL

sudo apache2ctl configtest
sudo systemctl restart apache2
sudo systemctl status apache2

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

o navegador vai avisar sobre o certificado autoassinado

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

Mas vamos ignorar isso, por enquanto, até usarmos o Let’s Encrypt.

Agora o teste no k8s

Faça alguns DNS…

Em cada nó k8s:

sudo nano /etc/hosts

e adicione lá

192.168.18.200 gitea.homelab
192.168.18.200 reg.homelab

Autoridade de Certificação Raiz

Em cada nó k8s:

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

E reinicie agora

Crie o segredo com as 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 deployment 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]disponível

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: Então, criando este deployment

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

Limpeza

kubectl delete -f alp2.yaml