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
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
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
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
- Dynamic versioning plugin for Poetry (pacote:
poetry-dynamic-versioning[plugin]
)
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
- Pacote servidor: postgresql
- Pacote cliente: postgresql-client
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
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
- Simuladores:
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
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