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.

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

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