sábado, 25 de fevereiro de 2012

O que ficou...


Há 12 anos estávamos eu e meus amigos de turma nos formando em Ciência da Computação na Universidade Estadual de Maringá (UEM). Em nossa colação de grau tive a honra de ser o orador geral de todos os formandos da formatura conjunta da UEM. No discurso que preparei (do qual lembro de apenas alguns trechos, infelizmente) optei por encerrá-lo adaptando um poema de Fernando Sabino. Nesse clima de nostalgia, recordo-me destas palavras:
"De tudo ficaram três coisas: 
A certeza de que estamos apenas começando,
A certeza de que é preciso continuar e
A certeza de que podemos ser interrompidos antes de terminar.
Fazer da interrupção um caminho novo,
Fazer da queda um passo de dança.
Do medo uma escada,
Do sonho uma ponte,
Da procura um encontro.
Fica a promessa do reencontro,
Fica o desejo de boa sorte,
Fica a vontade de que lutes e venças!"
Creio que são boas palavras de inspiração. É o que fica para todos nós...

Crédito da foto ao Paulo Roberto Crestani Júnior.

Utilizando o iptables ou ngninx para responder requisições na porta 80 como usuário não-root


Por questões de segurança jamais devemos permitir que serviços num servidor unix sejam executados como root. Isso permitiria que uma falha nesse serviço (e como desenvolvedores sabemos que essas falhas realmente acontecem) comprometesse todo o sistema.

Pelas mesmas restrições de segurança, não é permitido que usuários não-root escutem (realizem o bind de sockets) em portas inferiores à 1024. A questão é: como então executar um serviço (HTTP, no nosso exemplo) na porta 80 como usuário não-root?

Utilizarei o HTTP - que roda na porta 80 - como exemplo, pois provavelmente é o caso de uso mais popular. Imagino que você precise que um Tomcat, um Glassfish ou um JBoss seja executado no seu servidor. Normalmente estes serviços são inicializados na porta 8080. Apresento então duas solução possíveis:
  1. Caso você possua somente um serviço e um domínio, pode utilizar o redirecionamento através do iptables.
  2. Caso você possua vários serviços em portas diferentes e possivelmente vários domínios (virtual hosts) no mesmo servidor, utilize o nginx como proxy. (Sim, é possível fazer o mesmo com o Apache e mod_proxy ou AJP, mas o ngnix provou-se uma solução mais fácil, rápida, prática e com menor consumo de memória).
Exemplo de configuração com o iptables redirecionando as requisições na porta 80 para a 8080:

O REDIRECT de PREROUTING atende as requisições externas, e o REDIRECT de OUTPUT serve para redirecionar as requisições originadas do próprio servidor que estejam direcionadas à porta 80.

Exemplo de configuração com o ngninx atuando como proxy de requisições na porta 80 e redirecionando para a porta 8080:

Com esta configuração do ngnix, basta duplicar as linhas acima com as alterações convenientes e você pode ter dois Tomcats sendo executados no mesmo servidor nas portas 8080 e 8081, por exemplo, e redirecionar o myserver.mydomain.com para a porta 8080 e o myserver2.mydomain.com para a porta 8081. Dois virtual hosts, cada um num Tomcat diferente, no mesmo servidor.

quarta-feira, 22 de fevereiro de 2012

Spring 3.x Profiles e configurações diferentes do log4j


Uma das mais aguardadas e bem vindas novas funcionalidades do Spring Framework 3.x são os bean profiles, permitindo que você configure grupos de beans e escolha qual(is) destes grupos você deseja ativar durante o desenvolvimento, produção, teste etc. Outra boa novidade é o Java Configuration, permitindo que você configure os seus contextos do Spring utilizando somente código Java ao invés dos famigerados arquivos XML.

Nem tanto ao céu, nem tanto ao inferno. XML não é algo ruim. Bem usado, é uma ferramenta valiosa. Mas é fácil exagerar também. De antemão já adianto que o refactoring de arquivos de configuração do Spring que utilizam o Java Configuration é bem mais simples.

Algo que me incomodava no log4j era o fato dele ser configurado através de arquivos disponíveis no classpath como log4j.properties ou log4j.xml. Isso tornava trabalhoso o ato de utilizar configurações diferentes para ambientes diferentes (normalmente utilizando o maven para copiar o arquivo escolhido dependendo do profile utilizado).

Nada como a maravilha do software livre. Analisando o código-fonte, vi que utilizar arquivos de configuração do log4j diferentes para ambiente diferentes é mais simples do que eu pensava.

Com a configuração abaixo você pode utilizar dois arquivos de configuração do log4j: um para teste/desenvolvimento que imprima no console, e outro para produção que grave num rolling file e/ou envie notificações através do SNS, por exemplo.


segunda-feira, 20 de fevereiro de 2012

Notificações do log4j através do Amazon SNS

Como desenvolvedores e devops muitas vezes precisamos ser notificados de erros que ocorrem nas aplicações para podermos resolvê-los com o mínimo de downtime e transtorno possível aos nosso clientes e usuários.

Estes "erros" (condições anormais de uso) são registrados no sistema através de loggers. Se você desenvolve software e não utiliza logging, então o problema é mais embaixo. Imagino que o seu código simplesmente deixa o stacktrace das exceções "estourar" na cara do usuário. Perdoe-me, mas você não é profissional. Você finge que programa, e o pior: há quem acredite.

A mais popular implementação de logging em Java é o log4j. Normalmente além do logging para arquivo ou console do log4j, alguns desenvolvedores utilizando o SMTPAppender para enviar e-mails de notificação quando algum WARN é registrado na aplicação.

Utilizar o SNS, serviço de notificações da Amazon, é uma alternativa mais eficiente do que enviar e-mails pois:
  • Permite o baixo acoplamento entre o emissor das notificações (o logger) e seus assinantes (possivelmente os e-mails dos desenvolvedores e devops).
  • Num ambiente com vários servidores rodando a mesma aplicação seria uma situação comum em caso de erro todas estas instâncias enviarem o mesmo e-mail, lotando a caixa de e-mail dos assinantes das notificações.

Pensando nisso resolvi criar uma biblioteca (enorme: 3 classes por enquanto) que permite utilizar o SNS como Appender do log4j: https://github.com/insula/log4j-sns

Entre outras benesses está o fato dele implementar um "quiet period" padrão de 15 minutos, evitando que você receba mais de uma notificação com o mesmo stacktrace dentro do intervalo de 15 minutos.

Num ambiente de cloud computing com múltiplas instâncias de uma mesma aplicação provavelmente você desejará implementar uma assinatura HTTP para lidar com notificações repetidas ao invés de ficar recebendo o mesmo e-mail de várias instâncias diferentes. Quem sabe não vale a pena criar um serviço e disponibilizá-lo online? Já vejo múltiplas situações em que isso seria útil.

quarta-feira, 8 de fevereiro de 2012

Utilizando o Janrain com o Spring Security 3.1.x


Para quem ainda não conhece, o OpenID é um protocolo que permite que você se autentique num site/serviço utilizando as credenciais (normalmente login/senha, mas também poderia ser um certificado digital, por exemplo) de um terceiro confiável.

Esta iniciativa surgiu para tentar eliminar o problema de ter que guardar e lembrar de centenas (ou quase milhares para alguns) de combinações de login e senha diferentes. Assumo também que você, usuário consciente, não utiliza o mesmo login/senha para mais de um serviço. Pois caso positivo, se alguém descobrir a sua combinação - que presumo deva ser trivial - terá acesso a todos os sites e aplicações nos quais você está cadastrado.

Com o OpenID você pode delegar a autenticação da sua aplicação para um provedor de OpenID como o Google, Facebook, Twitter etc. Assim você pode utilizar o sistema de autenticação destes provedores ao invés de criar um próprio.

O Janrain é um serviço que integra vários provedores diferentes de OpenID, permitindo que você desenvolva sua aplicação somente com o Janrain e passe a utilizar vários provedores de OpenID rapidamente.

Para facilitar a vida de quem utiliza a excelente biblioteca de autenticação e autorização spring-security, criei um projeto LGPL que integra o Janrain com o spring-security. De bônus, já vem com componentes JSF2 prontos para usar. Podem conferir em https://github.com/insula/spring-security-janrain