Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Notas Klosowski

Esse site contêm algumas anotações minhas.

Para um conteúdo mais organizado recomendo visitar o meu blog.

Dev

Linguagens de Programação

Python

Instalar Aplicação

pipx

Site

O pipx permite instalar aplicações Python (pacotes) em VirtualEnv, disponibilizando seus executáveis para serem utilizados fora dele.

Instalação

Escolha uma das opções:

Gerenciador de pacotes:

apt install pipx

Manual:

python -m venv ~/.local/python-apps
~/.local/python-apps/bin/pip install pipx
ln -s ~/.local/python-apps/bin/pipx ~/.local/bin/pipx
Completion

Bash:

Gerenciador de pacotes:

echo 'eval "$(register-python-argcomplete3 pipx)"' > ~/.local/share/bash-completion/completions/pipx

Manual:

echo 'eval "$($HOME/.local/python-apps/bin/register-python-argcomplete pipx)"' > ~/.local/share/bash-completion/completions/pipx

Comandos

Listar aplicações instaladas:

pipx list --include-injected

Instalar aplicação:

pipx install <pacote>

Instalar aplicação no mesmo VirtualEnv de outra:

pipx inject <virtualenv> <pacote>

Atualizar todas as aplicações:

pipx upgrade-all --include-injected

Ambiente de Desenvolvimento

pyenv

Site

O pyenv permite instalar e gerenciar várias versões diferentes do Python.

Instalação

git clone https://github.com/pyenv/pyenv.git ~/.pyenv --single-branch --depth=1
ln -s ~/.pyenv/bin/pyenv ~/.local/bin/pyenv

# Dependências para compilar o Python
apt install make gcc zlib1g-dev libssl-dev

# Dependências opcionais para algumas libs da biblioteca padrão do Python
apt install libbz2-dev libncurses-dev libffi-dev libreadline-dev libsqlite3-dev liblzma-dev

# [Opcional] Melhora a performance
cd ~/.pyenv
src/configure
make -C src
Completion

bash:

ln -s ~/.pyenv/completions/pyenv.bash ~/.local/share/bash-completion/completions/pyenv
Atualização

Copiar script update-pyenv para ~/.local/bin.

Instalar Versões do Python

Listar versões disponíveis:

pyenv install -l

Instalar versão desejada:

pyenv install <versão>

Executáveis do Python podem ser encontrados em ~/.pyenv/versions/<versão>/bin/python.

Poetry

Site

Instalação

pipx install poetry

# Plugins
pipx inject poetry <pacote-do-plugin>
Completion

bash:

echo 'eval "$(poetry completions bash)"' > ~/.local/share/bash-completion/completions/poetry

Plugins

Configuração

Listar parâmetros:

poetry config --list

Recupera valor de um parâmetro:

poetry config <parâmetro>

VirtualEnvs

Listar VirtualEnvs do projeto:

poetry env list

Informações sobre o VirtualEnv atual:

poetry env info

Criar novo VirtualEnv com uma versão específica do Python:

poetry env use ~/.pyenv/versions/<versão>/bin/python

Remover VirtualEnv:

poetry env remove <nome do venv>

Rodar comando dentro do VirtualEnv:

poetry run <comando>

Abrir shell dentro do VirtualEnv:

poetry shell

Terraform

Instalação

Repositório APT

wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /etc/apt/keyrings.d/hashicorp-package.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings.d/hashicorp-package.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" > /etc/apt/sources.list.d/hashicorp.list
apt update && apt policy terraform
apt install terraform=1.9.8-1
apt-mark hold terraform

Completion

Bash:

# terraform -install-autocomplete
echo "complete -C '$(which terraform)' terraform" > /etc/bash_completion.d/terraform

Exemplos

Cloud

Serviços

Amazon Web Services (AWS)

Ferramentas auxiliares:

Cliente CLI

Instalação

curl -o awscliv2.zip https://awscli.amazonaws.com/awscli-exe-linux-x86_64-2.24.12.zip
unzip -q awscliv2.zip
sudo ./aws/install
rm -rf awscliv2.zip aws

Completion

Bash:

echo "complete -C \"$(which aws_completer)\" aws" > ~/.local/share/bash-completion/completions/aws

Configuração

Chave Simples

Cria configuração de forma iterativa:

aws configure
aws configure --profile=user1
AWS_PROFILE=localstack aws configure

Arquivos de configuração:

~/.aws/config:

[default]
region=us-west-1
#output=json

[profile user1]
region=us-east-1
#output=text

[profile localstack]
region=us-east-1
#output=table
endpoint_url=http://localhost:4566

~/.aws/credentials:

[default]
aws_access_key_id=ASIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token = IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE

[user1]
aws_access_key_id=ASIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
aws_session_token = fcZib3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE

[localstack]
aws_access_key_id = test
aws_secret_access_key = test

Integrado ao SSO

Cria configuração de forma iterativa:

aws configure sso
aws configure sso --profile=user1

Arquivos de configuração:

~/.aws/config:

[profile user1]
sso_session = my-sso
sso_account_id = 123456789012
sso_role_name = my-role
region = us-east-1
#output = json

[sso-session my-sso]
sso_region = us-east-1
sso_start_url = https://sso.mycompany.com/start
sso_registration_scopes = sso:account:access

Atualiza credenciais/Login:

aws sso login --profile=user1
AWS_PROFILE=user1 aws sso login

Testa Configuração

aws sts get-caller-identity
aws sts get-caller-identity --profile=user1
AWS_PROFILE=localstack aws sts get-caller-identity
AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_SESSION_TOKEN=test AWS_DEFAULT_REGION=us-east-1 AWS_ENDPOINT_URL=http://localhost:4566 aws sts get-caller-identity

Mocks

LocalStack

Verificar status:

curl -s http://localhost:4566/_localstack/init
curl -s http://localhost:4566/_localstack/init/ready

Imagem Docker:

services:
  aws:
    image: localstack/localstack:4.1.1
    restart: unless-stopped
    volumes:
      - aws-data:/var/lib/localstack
      - /var/run/docker.sock:/var/run/docker.sock
      - ./init.sh:/etc/localstack/init/ready.d/init.sh:ro  # Script para criar recursos
    ports:
      - 4566:4566
      - 4510-4559:4510-4559
volumes:
  aws-data:

PostgreSQL

Instalação

Debian

Docker

Imagem: postgres

Config

Databases

Lista banco de dados:

\l

Cria/Remove banco de dados:

CREATE DATABASE "database";
CREATE DATABASE "database" OWNER "role";
DROP DATABASE "database" WITH (FORCE);

Lista schemas:

\dn

Cria/Remove schema:

CREATE SCHEMA "schema";
DROP SCHEMA "schema" CASCADE;

Usuários

Lista roles:

\dg

Cria/Exclui role:

CREATE ROLE "role";
DROP ROLE "role";

Cria/Remove usuário:

CREATE USER "user@domain" WITH PASSWORD '12345';
DROP USER "user@domain";

Altera senha do usuário:

ALTER USER "user@domain" WITH PASSWORD '54321';

Lista roles dos usuários:

\drg

Atribui/Remove role ao usuário:

GRANT "role" TO "user@domain";
REVOKE "role" FROM "user@domain";

Lista acesso as bases de dados:

-- Bases que cada usuário consegue conectar
SELECT
  u.usename,
  (
    SELECT string_agg(d.datname, ',' ORDER BY d.datname)
    FROM pg_database AS d
    WHERE has_database_privilege(u.usename, d.datname, 'CONNECT')
  ) AS databases
FROM pg_user AS u
ORDER BY u.usename;

-- Usuários que conseguem conectar em cada base
SELECT
  d.datname AS database_name,
  (
    SELECT string_agg(u.usename, ',' ORDER BY u.usename)
    FROM pg_user AS u
    WHERE has_database_privilege(u.usename, d.datname, 'CONNECT')
  ) AS users
FROM pg_database AS d
ORDER BY d.datname;

Lista acesso aos schemas:

SELECT
  pg_namespace.nspname AS schema,
  a.privilege_type,
  a.is_grantable,
  e.role AS role
FROM pg_namespace
JOIN LATERAL (SELECT * FROM aclexplode(nspacl)) AS a ON true
JOIN (
  SELECT usesysid AS id, usename AS role FROM pg_user
  UNION
  SELECT oid AS id, rolname AS role FROM pg_roles
) AS e ON a.grantee = e.id;

Da/Remove acesso ao schema:

GRANT USAGE ON SCHEMA "schema" TO "role";
REVOKE USAGE ON SCHEMA "schema" FROM "role";

Lista acesso as tabelas:

SELECT * FROM information_schema.role_table_grants;

SELECT
  grantee AS role,
  table_catalog AS database,
  table_schema AS schema,
  table_name AS table,
  string_agg(privilege_type, ', ' ORDER BY privilege_type) AS privileges
FROM information_schema.role_table_grants
WHERE grantee != 'postgres' AND grantee != 'PUBLIC'
GROUP BY grantee, table_catalog, table_schema, table_name;

Da/Remove acesso à tabela:

GRANT SELECT ON TABLE "schema"."table" TO "role";
REVOKE SELECT ON TABLE "schema"."table" FROM "role";

Health Check

Documentação

Exemplos

docker-compose

services:
  app:
    image: app-image:latest
    command: sleep infinity
    environment:
      PGHOST: "pg"
      PGPORT: "5432"
      PGUSER: "username"
      PGPASSWORD: "password"
      PGDATABASE: "database"
      DATABASE_URL: "postgresql://username:password@pg:5432/database"
    depends_on:
      pg:
        condition: service_healthy
  pg:
    image: postgres:17.0
    restart: unless-stopped
    environment:
      POSTGRES_USER: "username"
      POSTGRES_PASSWORD: "password"
      POSTGRES_DB: "database"
    volumes:
      - pg-data:/var/lib/postgresql/data
    expose:
      - 5432
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "username", "-d", "database"]
      interval: 15s
      timeout: 5s
      retries: 4
  pgadmin:
    image: dpage/pgadmin4:8.12
    restart: unless-stopped
    environment:
      PGADMIN_DEFAULT_EMAIL: "user@test.com"
      PGADMIN_DEFAULT_PASSWORD: "password"
      PGADMIN_LISTEN_PORT: "5050"
    ports:
      - 5050:5050
    volumes:
      - ./pgadmin-servers.json:/pgadmin4/servers.json:ro
      - pgadmin-data:/var/lib/pgadmin
    depends_on:
      pg:
        condition: service_started
volumes:
  pg-data:
  pgadmin-data:

pgadmin-servers.json:

{
  "Servers": {
    "1": {
      "Name": "Database",
      "Group": "Servers",
      "Host": "pg",
      "Port": 5432,
      "SSLMode": "prefer",
      "Username": "username",
      "MaintenanceDB": "postgres"
    }
  }
}

Subir diversos bancos

/docker-entrypoint-initdb.d/databases.sql:

CREATE USER "user" WITH PASSWORD 'password';
CREATE DATABASE "database" OWNER "user";

GitHub Actions

jobs:
  job-name:
    runs-on: ubuntu-latest
    env:
      DATABASE_URL: "postgresql://username:password@127.0.0.1:5432/database"
    services:
      pg:
        image: postgres:17.0
        env:
          POSTGRES_USER: "username"
          POSTGRES_PASSWORD: "password"
          POSTGRES_DB: "database"
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U username -d database"
          --health-interval 15s
          --health-timeout 5s
          --health-retries 4

RabbitMQ

Estudo

Instalação

Debian

Pacote: rabbitmq-server

Docker

Imagem: rabbitmq

Config

Virtual Hosts

Listar virtual hosts:

rabbitmqctl -q list_vhosts

Criar virtual host:

rabbitmqctl add_vhost <nome>

Remover virtual host:

rabbitmqctl delete_vhost <nome>

Usuários

Listar usuários:

rabbitmqctl -q list_users

Criar usuários:

rabbitmqctl add_user <usuário> <senha>

Trocar senha do usuário:

rabbitmqctl change_password <usuário> <senha>

Remover usuário:

rabbitmqctl delete_user <usuário>

Listar permissões em um virtual host:

rabbitmqctl -q list_permissions --vhost <virtual_host>

Remover todas as permissões de um usuário em um virtual host:

rabbitmqctl clear_permissions --vhost <virtual_host> <usuário>

Atribuir permissões para um usuário ('.*' para todos os recursos):

rabbitmqctl set_permissions --vhost <virtual_host> <usuário> <config_perm> <write_perm> <read_perm>

Permitir que usuário acesso interface web:

rabbitmqctl set_user_tags <usuário> management

Plugins

Mostrar plugins disponíveis e quais estão habilitados:

rabbitmq-plugins list

Habilitar plugin sem o serviço rodando (ideal para colocar no Dockerfile):

rabbitmq-plugins enable --offline <plugin> [<plugin> ...]

Verificar se um plugin está habilitado:

rabbitmq-plugins -q is_enabled <plugin>

Health Check

Documentação

Verificar se o runtime está em execução:

rabbitmq-diagnostics -q ping

Informações gerais do nó:

rabbitmq-diagnostics -q status

Verificar se o RabbitMQ está em execução:

rabbitmq-diagnostics -q check_running

Verificar alarmes no nó:

rabbitmq-diagnostics -q check_local_alarms

Verificar conectividade das portas:

rabbitmq-diagnostics -q check_port_connectivity

Verificar se virtual hosts estão rodando:

rabbitmq-diagnostics -q check_virtual_hosts

Prometheus

URL: http://<hostname>:15692/metrics

Exemplos

docker-compose

services:
  rabbitmq:
    image: rabbitmq:3.11-management-alpine
    environment:
      RABBITMQ_DEFAULT_USER: "guest"
      RABBITMQ_DEFAULT_PASS: "guest"
      RABBITMQ_DEFAULT_VHOST: "/"
    ports:
      - 5672:5672
      - 15672:15672
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "-q", "check_running"]
volumes:
  rabbitmq-data:

Python

Exemplo em Python: rabbitmq-python.tar.gz

Rede

Acesso Remoto

SSH

Manter e compartilhar sessão

O tmux pode ser usado em conjunto com o ssh para manter a sessão caso a conexão seja perdida, ou compartilhar a tela com outros usuários.

Uma forma simples de fazer isso é instalar o tmux no servidor (apt install tmux, por exemplo), e configurar o alias ssht no seu computador, que pode ser feito no arquivo ~/.bash_aliases:

ssht() {
  ssh -t "$@" "tmux new -A -s 0"
}

Para o autocomplete funcionar, assim como ocorre no comando ssh, é necessário configurá-lo em ~/.local/share/bash-completion/completions/ssht:

source /usr/share/bash-completion/completions/ssh
complete -F _ssh ssht

Após reiniciar o shell será possível conectar no servidor usando ssht <endereço>, exemplo ssht localhost. E caso a conexão seja perdida, ou usando o comando Ctrl + b, d (se não foi alterado na configuração do tmux), basta usar o mesmo comando para reconectar no servidor e voltar a sessão que estava aberta.

Certificados TLS

Certificado Autoassinado

Gerar chave privada:

openssl genrsa -out privado.key 1024

openssl genpkey -algorithm ed25519 -out privado.key

openssl ecparam -list_curves
openssl ecparam -genkey -name secp256k1 -noout -out privado.key

Gerar certificado:

openssl req -x509 -new -key privado.key -out certificado.crt -subj '/CN=localhost' -days 365

openssl req -x509 -new -key privado.key -out certificado.crt -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:localhost.127.0.0.1.nip.io' -days 365

Comando único:

openssl req -x509 -newkey rsa:1024 -noenc -keyout privado.key -out certificado.crt -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost' -days 365

openssl req -x509 -newkey ed25519 -noenc -keyout privado.key -out certificado.crt -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost' -days 365

Requisição de Certificado

Gera requisição:

openssl req -new -key privado.key -out requisicao.csr -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost'

openssl req -newkey ed25519 -noenc -keyout privado.key -out requisicao.csr -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost'

Assina requisição:

openssl x509 -req -CA ca-certificado.crt -CAkey ca-privado.key -in requisicao.csr -out certificado.crt -copy_extensions copy -days 365

PKCS-12

Gera bundle do certificado e chave:

openssl pkcs12 -export -in certificado.crt -inkey privado.key -out combinado.pfx -passout pass:

openssl pkcs12 -export -in certificado.crt -inkey privado.key -out combinado.pfx -passout pass: -name nome-do-certificado

openssl pkcs12 -export -in certificado.crt -inkey privado.key -out combinado.pfx -passout pass:123456 -name nome-do-certificado

Visualizar Informações

Chave:

openssl rsa -in privado.key -noout -text -check
openssl rsa -in privado.key -pubout | openssl rsa -pubin -noout -text

openssl pkey -in privado.key -noout -text -check
openssl pkey -in privado.key -pubout | openssl pkey -pubin -noout -text -check

openssl ec -in privado.key -noout -text -check
openssl ec -in privado.key -pubout | openssl ec -pubin -noout -text

openssl pkcs12 -in combinado.pfx -info

Requisição de certificado:

openssl req -in requisicao.csr -noout -text -verify

Certificado:

openssl x509 -in certificado.crt -noout -text

Valida cadeia de certificados:

openssl verify -CAfile ca.crt -untrusted intermediario.crt servidor.crt
openssl verify -CAfile ca.crt -untrusted intermediario.crt ca.crt intermediario.crt folha.crt

Autoridade Certificadora (CA)

Makefile:

SERVER_HOST := server.127.0.0.1.nip.io
CLIENT_HOST := client.127.0.0.1.nip.io

.PHONY: certs clean run-server run-server-mtls run-client run-client-verify run-client-mtls

certs: ca.key ca.crt server.127.0.0.1.nip.io.key server.127.0.0.1.nip.io.crt client.127.0.0.1.nip.io.key client.127.0.0.1.nip.io.crt

ca.key:
	openssl genpkey -algorithm ed25519 -out $@

ca.crt: ca.key
	openssl req -x509 -new -key $< -out $@ -subj '/CN=Minha CA' -days 3653

%.key:
	openssl genpkey -algorithm ed25519 -out $@

%.csr: %.key
	openssl req -new -key $< -out $@ -subj '/CN=$*'

%.crt: %.csr ca.crt ca.key
	openssl x509 -req -CA ca.crt -CAkey ca.key -in $< -out $@ -copy_extensions copy -days 365

clean:
	rm -f *.key *.crt *.csr

run-server: $(SERVER_HOST).key $(SERVER_HOST).crt
	openssl s_server -port 4433 -key $(SERVER_HOST).key -cert $(SERVER_HOST).crt

run-server-mtls: $(SERVER_HOST).key $(SERVER_HOST).crt ca.crt
	openssl s_server -port 4433 -key $(SERVER_HOST).key -cert $(SERVER_HOST).crt -Verify 1 -verify_return_error -CAfile ca.crt

run-client:
	openssl s_client -connect $(SERVER_HOST)

run-client-verify: ca.crt
	openssl s_client -connect $(SERVER_HOST) -verify_return_error -CAfile ca.crt

run-client-mtls: ca.crt $(CLIENT_HOST).key $(CLIENT_HOST).crt
	openssl s_client -connect $(SERVER_HOST) -verify_return_error -CAfile ca.crt -key $(CLIENT_HOST).key -cert $(CLIENT_HOST).crt

HTTPS com mTLS

Certificados

Gerar certificados:

# Servidor
openssl req -x509 -newkey ed25519 -noenc -keyout server.key -out server.crt -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost' -days 365

# Cliente
openssl req -x509 -newkey ed25519 -noenc -keyout client.key -out client.crt -subj '/CN=client' -days 365

Servidor

Executar servidor de exemplo com OpenSSL:

openssl s_server -port 4433 -www -cert server.crt -key server.key -CAfile client.crt -Verify 1 -verify_return_error

Cliente

Realizar requisições:

# cURL
curl -v --cacert server.crt --cert client.crt --key client.key https://localhost:4433/

# HTTPie
http -v --cert=client.crt --cert-key=client.key --verify=server.crt https://localhost:4433/

Proxy

Servidor

Proxy HTTPS

O mitmproxy pode ser utilizado como servidor proxy para visualizar as requisições HTTPS feitas, estando o cliente no mesmo dispositivo ou não. Ele pode ser executado através do docker:

# Versão TUI
docker run --rm -it -v "$(pwd)/cert:/home/mitmproxy/.mitmproxy" -p 8080:8080 mitmproxy/mitmproxy

# Versão WEB
docker run --rm -it -v "$(pwd)/cert:/home/mitmproxy/.mitmproxy" -p 8080:8080 -p 127.0.0.1:8081:8081 mitmproxy/mitmproxy mitmweb --web-host 0.0.0.0

Ao subir o serviço, será criado automaticamente um certificado de CA em cert/mitmproxy-ca-cert.pem (se não existir). Esse certificado deve ser configurado como uma CA confiável no cliente, além de configurar o proxy HTTP na porta 8080.

A versão TUI mostrará as requisições no terminal, enquanto a versão WEB pode ser acessada na porta 8081.

Cliente

Requisições HTTPS via Proxy

# Define proxy
export HTTP_PROXY=http://127.0.0.1:8080
export HTTPS_PROXY=http://127.0.0.1:8080

# cURL sem validar CA
curl -v -k https://duckduckgo.com/

# cURL informando certificado da CA
curl -v --cacert mitmproxy-ca-cert.pem https://duckduckgo.com/

# HTTPie sem validar CA
http -v --verify=no https://duckduckgo.com/

# HTTPie informando certificado da CA
http -v --verify=mitmproxy-ca-cert.pem https://duckduckgo.com/

Requisições via SOCKS

# Define proxy
export ALL_PROXY='socks5://127.0.0.1:9050'  # Resolve DNS localmente
export ALL_PROXY='socks5h://127.0.0.1:9050'  # Resolve DNS no servidor

Redirecionamento de Porta

socat

O socat é um programa para fazer encaminhamento de sockets. Ele pode ser utilizado para abrir uma porta local e redirecionar o tráfego para outro endereço. Exemplo:

# Porta TCP
socat -dd TCP-LISTEN:8080,fork,reuseaddr TCP:10.0.0.1:80

# Porta UDP
socat -dd UDP-LISTEN:8080,fork,reuseaddr UDP:10.0.0.1:8000

# UNIX Socket
socat -dd TCP-LISTEN:8080,fork,reuseaddr UNIX:/var/run/http.sock

Sockets

UNIX

Servidor UNIX

socat -dd stdio unix-listen:app.sock,fork

Cliente UNIX

socat -dd stdio unix-connect:app.sock

UDP

Servidor UDP

nc -vulp 8000

socat -dd stdio udp-listen:8000,fork,reuseaddr

Cliente UDP

nc -vu localhost 8000

socat -dd stdio udp-connect:localhost:8000

TCP

Servidor TCP

nc -vlp 8000

socat -dd stdio tcp-listen:8000,fork,reuseaddr

Cliente TCP

nc -v localhost 8000

socat -dd stdio tcp-connect:localhost:8000