Arquivo

Posts Tagged ‘autenticação’

Como Integrar o Apache Shiro a uma Aplicação JSF

O Shiro é um framework de segurança da Apache escrito em Java que permite a criação de soluções para autenticação, autorização, criptografia, gerenciamento de sessão e ainda fornece várias implementações de cache. Ele é simples de configurar e tem vários pontos de extensão que nos permitem intervir sobre seu funcionamento – são características de um framework bem projetado -, mas as configurações padrão já são suficientes para uma aplicação de pequeno porte.

Figura 1 – Arquitetura do Shiro

Nesse artigo, vou mostrar um exemplo de como integrar o Shiro a uma aplicação JSF. Nosso modelo será composto por uma enum chamada Permissao, uma enum Perfil para agrupar as permissões, e a entidade Usuario, que possui um Perfil:

public enum Permissao {
   CRIAR_PEDIDO, 
   LISTAR_PEDIDOS;
}

public enum Perfil {
   ADMINISTRADOR(Permissao.CRIAR_PEDIDO, Permissao.LISTAR_PEDIDOS);
   private List<Permissao> permissoes;
   private Perfil(Permissao... permissoes) {
      this.permissoes = Arrays.stream(permissoes).
         collect(Collectors.toList());
   }
}

@Entity
@Table(name = "TBL_USUARIO")
@TypeDefs(value = {@TypeDef(name = "TIPO_PERFIL" ...)})
public class Usuario {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "PK_USUARIO")
   private Long id;
   @Column(name = "NM_USUARIO")
   private String nome;
   @Column(name = "COD_PERFIL")
   @Type(type = "TIPO_PERFIL")
   private Perfil perfil;
}

Há várias formas de configurar o Shiro. Vou mostrar como configurá-lo à partir do arquivo de configuração shiro.ini. Precisamos incluir duas dependências no arquivo pom.xml – isso é o básico para o Shiro ser integrado a uma aplicação web:

<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-core</artifactId>
   <version>1.3.2</version>
</dependency>
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-web</artifactId>
   <version>1.3.2</version>
</dependency>

Em seguida, vamos configurar o arquivo shiro.ini, que deve ficar no classpath – eu costumo colocar em /src/main/resources. As seções desse arquivo agrupam propriedades que determinam o comportamento do Shiro. Basicamente, informamos qual é o Realm utilizado (será explicado mais adiante), qual é a página de autenticação para a qual o Shiro redirecionará o usuário não autenticado, para onde o usuário será redirecionado após o logout e também permite que informemos que há páginas privadas que só podem ser acessadas por usuários que tenham determinadas permissões. No nosso exemplo, a página “criarpedido.xhtml” só pode ser acessada por usuários que contenham a permissão “CRIAR_PEDIDO”.

[main]
apprealm = br.com.app.autorizacao.AppRealm
securityManager.realms = $apprealm
authc.loginUrl = /publico/index.xhtml
logout.redirectUrl = /publico/index.xhtml

[users]

[roles]
ADMINISTRADOR = *

[urls]
/privado/criarpedido.xhtml =  authc, perms["CRIAR_PEDIDO"]

No arquivo web.xml, configuraremos os filtros e listeners do Shiro e também informaremos quais são as páginas que responderão pelos códigos de erro HTTP.

<filter>
   <filter-name>ShiroFilter</filter-name>
   <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>

<filter-mapping>
   <filter-name>ShiroFilter</filter-name>
   <url-pattern>/*</url-pattern>
   <dispatcher>REQUEST</dispatcher>
   <dispatcher>FORWARD</dispatcher>
   <dispatcher>INCLUDE</dispatcher>
   <dispatcher>ERROR</dispatcher>
</filter-mapping>

<listener>
   <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener
</listener-class>
</listener>
	
<error-page>
   <error-code>401</error-code>
   <location>/publico/acessonegado.xhtml</location>
</error-page>

<error-page>
   <error-code>403</error-code>
   <location>/publico/acessonegado.xhtml</location>
</error-page>

<error-page>
   <error-code>404</error-code>
   <location>/publico/paginanaoencontrada.xhtml</location>
</error-page>

<error-page>
   <error-code>500</error-code>
   <location>/publico/erro.xhtml</location>
</error-page>

Essa é toda a configuração básica que qualquer aplicação web precisa para ser integrada ao Shiro. De agora em diante, começaremos a implementação do nosso mecanismo de autenticação e autorização. Só então você verá como é simples trabalhar com o Shiro. Uma peça importante do mecanismo de autenticação é o AuthenticationToken, que é a classe que mantém as credenciais do usuário. Você pode escolher uma das implementações dessa interface disponíveis, mas vamos criar uma implementação dela que recebe o ID do usuário:

public class IdAuthenticationToken implements AuthenticationToken {
   private Integer userId;

   public IdAuthenticationToken(Integer userId) {
      this.userId= userId;
   }

   @Override
   public Object getPrincipal() {
      return this.id;
   }

   @Override
   public Object getCredentials() {
      return this.id;
   }
}

Você precisará informar ao Shiro que um usuário está se autenticando. Você pode fazer isso à partir de um servlet, campos de input em um formulário de uma tela que é tratada por um ManagedBean, etc. Eu fiz através de um servlet porque antes que o usuário se autenticasse na minha aplicação era feita client authentication contra um Apache Server para validar o certificado digital. Modifiquei um pouco o código para indicar que as credenciais do usuário estão vindo pela request, que no meu caso era um post realizado pela aplicação que rodava em um JBoss debaixo daquele Apache. A credencial é apenas o atributo “userId”, que foi fornecido pela aplicação que validou o certificado digital.

@WebServlet(displayName = "AutenticacaoServlet", 
   name = "AutenticacaoServlet", urlPatterns = "/autenticar")
public class AutenticacaoServlet extends HttpServlet {

protected void doPost(HttpServletRequest request, 
      HttpServletResponse response)
     throws ServletException, IOException {
   Integer userId = (Integer) request.getAttribute("userId");
   Subject subject = SecurityUtils.getSubject();
   subject.login(new IdAuthenticationToken(token, userId));
   subject.checkPermission("CRIAR_PEDIDO");

   response.sendRedirect(request.getContextPath() + 
      "/private/criarpedido.xhtml?faces-redirect=true";

O Realm é um componente que interpreta os artefatos de segurança da aplicação – como usuários, regras e permissões – para o Shiro. Sendo o Realm a fonte de dados para autorização, podemos dizer, grosso modo, que ele é o DAO, ou melhor, um repository, que serve um modelo de autorização e autenticação.

Figura 2 – Sequência Simples de Autenticação

public class AppRealm extends SimpleAccountRealm {

   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(
       AuthenticationToken token) throws AuthenticationException {
      IdAuthenticationToken authToken = (IdAuthenticationToken) token;
      Optional<Usuario> usuario = usuarioDao.buscar(token.getUserId());
      return new SimpleAuthenticationInfo(
         usuario.get(), usuario.get().getId(), getName());
   }

   @Override
   protected AuthorizationInfo doGetAuthorizationInfo(
        PrincipalCollection principals) {
      Set<String> roles = new HashSet<>();
      Set<String> permissions = new HashSet<>();

      Usuario usuario = (Usuario) SecurityUtils.getSubject().getPrincipal();
      Perfil perfil = usuario.getPerfil();

      roles.add(perfil.name());

      perfil.getPermissoes().forEach(a -> {
         permissions.add(a.nome());
      });

      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
      info.setRoles(roles);
      info.setStringPermissions(permissions);
      return info;
   }

   @Override
   public String getName() {
      return getClass().getName();
   }

   @Override
   public boolean supports(AuthenticationToken token) {
      return IdAuthenticationToken.class.equals(token.getClass());
   }
}

Utilizamos a implementação SimpleAccountRealm, que é suficiente para o que nos propusemos a fazer. Se você quiser que o Shiro fique automaticamente consultando o banco de dados para carregar as permissões, basta utilizar um JdbcRealm e adicionar a consulta que o Shiro deve utilizar no arquivo shiro.ini.

Nesse momento, já temos um mecanismo que gerencia as credenciais do usuário e autoriza o acesso às páginas informadas na configuração inicial. Se você precisar fazer checagens de permissão ou verificar se o usuário está autenticado programaticamente, você deve acessar o Subject através do SecurityUtils ou utilizar as anotações do Shiro nos métodos das suas classes que devem ser autorizados.

Recomendações para Migração de Aplicações JSF “Puras”

Se você tem uma implementação de PhaseListener que de alguma forma toma decisões com base na URL acessada em sua aplicação JSF, remova-a. Na verdade, você deveria remover filtros, servlets e quaisquer outras implementações interessadas em autorização. Quem cuidará disso é o Shiro – mais especificamente a sua implementação de Realm.

É comum que aplicações JSF tenham uma ExceptionHandlerFactory para interceptar e tratar exceções nas páginas. Isso também não será necessário, pois o Shiro contém a ShiroException e suas variantes. Você também pode definir páginas específicas para tratar os códigos de erro HTTP mapeadas no seu arquivo web.xml.

Referências

1. [http://shiro.apache.org/reference.html]
2. [https://shiro.apache.org/java-authorization-guide.html]
3. [https://shiro.apache.org/authorization.html]
4. [https://shiro.apache.org/architecture.html]
5. [https://shiro.apache.org/configuration.html]
6. [http://galluzzo.com.br/?p=698]
7. [https://dzone.com/articles/java-security-framework-apache]
8. [http://czetsuya-tech.blogspot.com/2012/10/how-to-integrate-apache-shiro-with.html]
9. [http://www.javastutorial.com/2016/03/how-to-use-apache-shiroauthentication.html]

Anúncios

Implementação de Autorização com Token Utilizando RESTEasy

Gosto bastante de desenvolver orientado a aspectos. A especificação JAX-RS possibilita implementar um mecanismo de autorização simples para seu web service REST. Um mecanismo de segurança simples ainda é melhor do que não ter segurança e a segurança deve ser definida como parte da arquitetura e não como uma funcionalidade.

Nesse exemplo, vamos mostrar como implementar um mecanismo de autorização baseado em token que é verificado em um interceptador do RESTEasy. Você poderia utilizar um ContainerRequestFilter ao invés do interceptor, mas você teria que utilizar a annotation @NameBinding em conjunto com a sua annotation para só então poder utilizá-la para anotar seu filtro.

1. Crie um enum que será utilizado para parametrizar sua anotação.

public enum Role {
   AUTHENTICATION_REQUIRED;
}

2. Crie uma anotação que utiliza a enum definida anteriormente para criar uma política de segurança. Essa anotação e aquela enum serão verificadas no interceptador. Você poderia utilizar outros métodos para identificar os recursos onde a política se aplicará, mas a combinação de enum e anotação é simples e elegante.

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface SecurityPolicy {
   Role[] value() default {};
}

3. Implemente um interceptador que verifica a anotação criada e a presença do atributo “TOKEN” no header da request. Note que além da anotação que criamos anteriormente (SecurityPolicy), estamos testando as anotações padrão PermitAll e DenyAll que poderiam estar anotando o recurso e são mais abrangentes que a nossa. Se tudo é permitido ou se tudo é negado, não faz sentido fazer uma verificação mais granular.

@Provider
@ServerInterceptor
public class SecurityInterceptor implements PreProcessInterceptor {
   @Override
   public ServerResponse preProcess(HttpRequest request, 
        ResourceMethod methodInvoked) 
      throws Failure, WebApplicationException {
      Method method = methodInvoked.getMethod();
      if (method.isAnnotationPresent(PermitAll.class)) {
         return null;
      }
      if (method.isAnnotationPresent(DenyAll.class)) {
         return new ServerResponse("Não pode acessar esse recurso",
         Status.UNAUTHORIZED.getStatusCode(), 
         new Headers<Object>());
      }
      if (method.isAnnotationPresent(SecurityPolicy.class)) {
         SecurityPolicy rolesAnnotation = 
           method.getAnnotation(SecurityPolicy.class);
         List<Role> roles = Arrays.asList(rolesAnnotation.value());
         if (roles.contains(Role.AUTHENTICATION_REQUIRED)) {
            HttpHeaders headers = request.getHttpHeaders();
            List<String> authorization = 
              headers.getRequestHeader("TOKEN");
            if(authorization != null && !authorization.isEmpty())
            {
               String token = authorization.get(0); 
               boolean autorizado = /*regras de autorizacao*/;
               if(autorizado){
                  // Deve-se retornar nulo para que o 
                  // processamento da request continue normalmente
                  return null;
               }
            }
            return new ServerResponse("Usuário não autorizado", 
              Status.FORBIDDEN.getStatusCode(),
              new Headers<Object>());
         }
      }
      // Deve-se retornar nulo para que o 
      // processamento da request continue normalmente
      return null;
   }
}

4. Crie um recurso e anote o método que exige a aplicação da política de segurança

@Path("/usuario")
public class UsuarioResource {
 
  @EJB
   private UsuarioService service;

   @GET
   @SecurityPolicy(Role.AUTHENTICATION_REQUIRED)
   @Path("/buscar")
   @Produces(MediaType.APPLICATION_JSON)
   public Response buscar(@PathParam("id") String id) {
      try {
         Usuario usuario = service.buscar(id);
         ResponseUsuario respUsuario = new ResponseUsuario();
         respUsuario.setNome(usuario.getNome());
         return Response.status(Response.Status.OK).
            entity(respUsuario).
            header("Content-type", "application/json; charset=utf-8").
            build();
      } catch (ServicoException e) {
          return Response.status(Response.Status.FORBIDDEN).
            entity("Nao foi possivel localizar o usuario.").
            header("Content-type", "application/json; charset=utf-8").
            build();
      }
      return Response.status(Response.Status.UNAUTHORIZED).
        entity("Usuário não autorizado.").
        header("Content-type", "application/json; charset=utf-8").
        build();
   }
}

Você poderia utilizar algum navegador para testar o funcionamento do seu web service, mas prefiro utilizar o SOAPUI. Se você tiver alguma problema relacionado a certificado do Java, dê uma olhada nesse artigo.

token

Figura 1 – Interface do SOAPUI

Note o parâmetro “TOKEN” que passamos no cabeçalho da request. O ideal é que o valor seja obtido do próprio web service, talvez acessando o banco de dados, e que este tenha um tempo de expiração que faça sentido para o negócio e para alguma política de segurança da informação de nível operacional.

Referências

1. [http://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey
2. [https://www.infoq.com/br/news/2012/10/autenticacao-rest
3. [http://blog.rivendel.com.br/2013/06/07/seguranca-em-apis-rest-parte-1/
4. [http://www.slideshare.net/stormpath
5. [http://www.developerscrappad.com/1814/java/java-ee/rest-jax-rs/java-ee-7-jax-rs-2-0-simple-rest-api-authentication-authorization-with-custom-http-header/
6. [http://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey
7. [https://www.mkyong.com/webservices/jax-rs/get-http-header-in-jax-rs/
8. [http://howtodoinjava.com/resteasy/jax-rs-resteasy-basic-authentication-and-authorization-tutorial/
9. [http://howtodoinjava.com/resteasy/jax-rs-2-0-resteasy-3-0-2-final-security-tutorial/[

Autenticação no Subversion com Certificado Digital

Se o servidor do Subversion estiver utilizando uma camada de segurança baseada em certificado digital, você precisará fazer algumas configurações para utilizar clientes em linha de comando – como o Svnmerge, por exemplo. Seguem os passos necessários para fazer a configuração da autenticação no Windows.

1. Abra o arquivo abaixo para edição:

C:\Users\{USUARIO}\AppData\Roaming\Subversion\servers

2. Altere ou inclua as linhas abaixo no arquivo:

[global]
store-passwords = yes
store-ssl-client-cert-pp = yes
ssl-client-cert-file={CAMINHO_CERTIFICADO_DIGITAL}

3. Apague o diretório abaixo, pois ele é o cache de credenciais do Subversion:

C:\Users\{USUARIO}\AppData\Roaming\Subversion\auth

Na próxima vez que utilizar seu cliente do Subversion, você terá que informar o PIN (Personal Identification Number) do certificado, o usuário e a senha para autenticação no servidor do Subversion.

Autorização Segura de Dispositivos com Certificado de Atributo na Internet das Coisas

Conforme o artigo Os Riscos de Segurança na Internet das Coisas, a Internet das Coisas é um conceito relacionado a objetos que podem interagir com o ambiente e entre si por diversos meios a qualquer momento e de forma autônoma para realizarem determinados objetivos. Devido a essa autonomia, esses objetos são chamados de “inteligentes”. Esses objetos são máquinas, várias delas utensílios domésticos, com um software embarcado que se comunicam utilizando o conceito máquina para máquina onde as principais tecnologias são sensores e redes sem fio. Estimativas mostram que a Internet das Coisas será composta de bilhões de dispositivos na próxima década, o que direcionará as estratégias de negócio das empresas e trará novos desafios à segurança: os cibercriminosos terão uma superfície de ataque maior, o que demandará meios mais seguros para se autenticar e autorizar dispositivos. Hoje, não há um padrão para autenticação ou autorização de dispositivos na Internet das Coisas, o que é importante para que a interoperabilidade das tecnologias seja mantida.

A autenticidade é considerada crítica para a confiabilidade da IoT [12] e é necessária uma forma de autenticação que valide a identidade de um dispositivo que deseja se comunicar com outro e também é necessária uma forma de recuperar as permissões dos dispositivos autenticados de forma segura e padronizada, o que é essencial para manter a interoperabilidade dos dispositivos na IoT. Não existem padrões específicos para autenticação e autorização M2M.

Um certificado digital X.509 é um padrão já estabelecido que tem por finalidade a autenticação forte, mas ele também poderia ser utilizado para a criação de um serviço de autorização embora com limitações [4][5]. Um mecanismo de autorização granular baseado em certificados de atributos pode ser uma solução para o problema da autorização confiável [12] e pode resolver outro problema inerente ao mundo IoT, que é a interoperabilidade dos dispositivos.

O objetivo desse artigo é mostrar que os certificados de atributo podem ser utilizados para a criação de mecanismos de autorização segura e granular para atender às necessidades da segurança na comunicação M2M na IoT que foram apresentadas no artigo Os Riscos de Segurança na Internet das Coisas. Para atingir esse objetivo, primeiro será demonstrada a falta de flexibilidade do uso de certificados digitais de chave pública em mecanismos de autorização.

Autorização de Dispositivos com Certificado Digital de Chave Pública

A quantidade de dispositivos que interagem para tornar a IoT possível demanda uma forma mais confiável e padronizada de autenticação. É necessário identificar que dispositivo está requerendo acesso para posteriormente autorizar o uso de recursos protegidos. O porte da IoT incide sobre vários domínios e envolve várias tecnologias proprietárias [6]. É necessária uma forma para permitir que os usuários de um sistema tenham a confiança de que as informações e os serviços sendo trocados possam de fato ser invocados.

Um dos princípios da comunicação M2M é a autenticação mútua [1]: somente dispositivos autenticados podem acessar a rede e outros dispositivos e qualquer dispositivo M2M deve se autenticar em um servidor antes de aceitar qualquer dado, como por exemplo comandos e atualizações. Isso garantirá que dados coletados por um servidor estão vindo de um dispositivo legítimo e é garantido ao dispositivo que ele está se comunicando com um servidor confiável.

Quando uma conexão segura é estabelecida utilizando TLS/SSL (Transport Layer Security/Secure Sockets Layer), a troca de mensagens ocorre entre o cliente – que sempre inicia a conexão – e um servidor [13]. O primeiro conjunto de mensagens é o protocolo de handshake (acordo entre as partes visando estabelecer uma conexão) e só depois de finalizado o handshake o cliente e o servidor iniciam o protocolo de transferência de dados. Os objetivos do handshake são:

  • Estabelecer a variante do protocolo utilizada – SSLv3, TLVSv1, etc.;
  • Enviar os dados de autenticação – um certificado X.509 por exemplo;
  • Estabelecer um identificador de sessão para que a sessão possa ser reiniciada se necessário;
  • Negociar o algoritmo criptográfico.

Os procedimentos de autenticação devem ser completados entre os dispositivos antes de inicializar a transferência de dados. Para haver transferência de dados, é necessário que as partes confiem uma na outra. Autenticação é justamente o processo de estabelecimento de confiança na identidade de uma entidade [8].

Todos os sistemas utilizam algo que identifique o usuário para posteriormente verificar o que esse usuário pode fazer (permissões de acesso) [8]. Isso significa que o dispositivo está sendo identificado, mas não significa necessariamente que sua identidade está sendo autenticada.

Normalmente, a autenticação de um usuário é feita a partir de um par composto por identificador e senha, mas nesse modelo a autenticação tem baixa confiabilidade, pois é relativamente simples para um cibercriminoso se apoderar dessas credenciais através de um ataque de força bruta, de dicionário ou engenharia social.

Uma das formas de melhorar a confiabilidade da autenticação é utilizando um par de chaves privada e pública junto com um certificado digital [1]. Esse par pode ser gerado individualmente durante a fabricação do dispositivo e pode ser instalado com o certificado correspondente.

Um certificado de chave pública (do inglês, public-key certificate – PKC) é um arquivo digital que agrega uma chave pública (a chave de um par de chaves que é conhecida publicamente), algumas outras informações sobre o proprietário e sobre o certificado em si que é assinado digitalmente com a chave privada da AC (Autoridade Certificadora) que o emitiu [7]. Uma AC é uma autoridade que é confiável por um ou mais usuários para criar e assinar certificados de chaves públicas. Para dar suporte ao gerenciamento de chaves públicas e serviços de autenticação, criptografia, integridade e não repúdio, é necessária uma infraestrutura de chaves públicas (do inglês, public-key infrastructure – PKI). Os certificados digitais X.509 foram projetados para representar identidades em esquemas multiplataforma e multidomínios.

pki1

Para que um usuário seja capaz de confiar na chave pública de outro usuário como forma de garantir autenticidade, essa chave deve ser obtida de uma fonte confiável, a AC, que certifica uma chave pública emitindo o certificado de chave pública que liga essa chave à entidade que é a proprietária da chave privada correspondente [7]. Emitir um PKC significa assinar uma coleção de informações (nome do usuário, período de validade, algoritmo de criptografia, etc.).

A verificação da validade de um certificado é feita testando-se sua expiração e sua revogação. A validação de data de expiração é trivial, pois esse é um dos atributos do certificado. Para que os serviços de autenticação possam realizar testes de revogação, a AC deve publicar a LCR (Lista de Certificados Revogados) [3]. Como a LCR é publicada periodicamente, as informações sobre a revogação podem não estar disponíveis imediatamente. Pode-se utilizar outro mecanismo, como o OCSP (Online Certificate Status Protocol) [9], que permite a verificação em tempo real de um certificado junto à entidade certificadora. É possível combinar os dois mecanismos na criação de um mecanismo de autenticação: primeiro, a consulta pode ser feita contra a OCSP; caso o serviço OCSP esteja indisponível, pode-se fazer o download da LCR para a verificação local.

Um PKC resolve o problema da autenticação incluindo um terceiro confiável – a AC – e disponibilizando informações e serviços que podem ser utilizados para validá-lo. O PKC também resolve o problema da criptografia da comunicação utilizando o conceito de chaves pública e privada: uma é utilizada para criptografar e a outra para descriptografar uma mensagem. Ele também pode conter as informações necessárias para se construir um mecanismo de autorização padronizado [4].

Autorização é a garantia de direitos, o que inclui a garantia de acesso baseada nos direitos de acesso [8]. Para construir um serviço de autorização, um dispositivo deve ser capaz de declarar suas capacidades e características para outro dispositivo de uma maneira verificável [11]: uma geladeira, por exemplo, pode ter um atributo que lhe dê autoridade para acessar a Internet em busca dos itens alimentícios que estão faltando e disponibilizar essas informações para seus proprietários. A própria geladeira ou o servidor onde ela se autenticou deve enviar seus atributos para um serviço de autorização no destino para que a geladeira seja autorizada.

Embora um certificado digital possa ser utilizado para a criação de um mecanismo de autorização, ele apresenta diversos pontos negativos quando utilizado para esse propósito [4] [11]. Dentre eles:

  • Todos os atributos devem ser conhecidos e definidos antes da emissão do certificado, ou seja, para revogar um atributo, é necessário revogar o próprio certificado;
  • A autenticação em uma determinada rede pode ser feita com certificado digital, mas supondo que os privilégios nessa rede são muito particulares, o mecanismo de autorização será definido localmente com atributos vindos de outras fontes;
  • Informações de autorização frequentemente não têm o mesmo tempo de vida de uma chave pública;
  • Quando a informação da autorização é inserida em uma extensão PKC, o resultado geral é menor do que o tempo de vida útil de um PKC;
  • O proprietário do PKC normalmente não é autoritativo para a informação de autorização. Isso resulta em passos adicionais para o proprietário do PKC obter informações de autorização da fonte autoritativa.

O PKC não é flexível o bastante para lidar com atributos. Como exemplo, vamos supor que a autorização de um relógio “inteligente” que dentre outras capacidades acessa um serviço que faz geolocalização seja desenvolvido com base em certificado digital. O certificado digital emitido para esse dispositivo terá de ter um campo com o atributo referente à função de geolocalização. Para revogar apenas essa funcionalidade, seria necessário revogar e reemitir o próprio certificado, pois qualquer alteração em seu estado interno causaria perda da integridade.

A maior vantagem de se adotar um padrão para autorização é a garantia de interoperabilidade entre os dispositivos, pois se não fosse assim, cada fabricante criaria um mecanismo de autorização válido apenas para seus dispositivos em seus domínios. As limitações do PKC incentivam o desenvolvimento de serviços de autorização locais, o que acaba impactando na interoperabilidade dos dispositivos. Interoperabilidade é um pressuposto da IoT.

Autorização de Dispositivos com Certificado de Atributo

O propósito principal de uma PKI é a autenticação forte através do uso de certificados digitais, mas a autenticação não é suficiente para se determinar quem pode fazer o quê em um dado subsistema [2]. Um mecanismo de autorização mais granular [6] e especializado é necessário para preencher essa lacuna deixada pelo PKC.

Em muitos contextos, a identidade do dispositivo não é o critério utilizado para decisões de controle de acesso, mas as informações de autorização precisam estar relacionadas a uma identidade. Os certificados digitais de atributo (CA) X.509 estabelecem uma separação clara entre o processo de autenticação e o processo de autorização [4]. Um CA tem uma estrutura de dados semelhante à do PKC, mas sem uma chave pública. Esses atributos podem representar grupos, regras, autorização de segurança ou outras autorizações.

Um CA é assinado digitalmente por uma AA (Autoridade de Atributo) que liga valores de atributos (privilégios) a informações de identificação sobre seu proprietário [7], o que lhe garante autenticidade – ao assinar, a AA insere sua chave criptográfica no CA. A AA é responsável pela emissão, gerenciamento e revogação de certificados de atributos.

Os CAs oferecem um mecanismo de autorização segura para funções de controle de acesso [4] que podem ser utilizados pela AA. Há dois modelos para a divulgação ou publicação dos atributos: pull e push.

No modelo push, os CAs são entregues pela AA diretamente para o dispositivo, que será responsável por enviar seus CAs para um servidor, o que reduz a complexidade do serviço de autorização no servidor. Esse modelo é aplicável na comunicação inter-domínios onde as permissões de um cliente devem ser atribuídas dentro do domínio do servidor ao invés de dentro do domínio do cliente. Esse modelo só é confiável devido à assinatura digital do certificado de atributo, que permite ao serviço de autorização do servidor verificar a autenticidade e a integridade das informações.

push

No modelo pull, o cliente se autentica no servidor e o servidor faz a requisição dos atributos diretamente para um repositório acessível para a consulta mantido pela AA. Nesse modelo, para revogar um certificado, bastaria removê-lo do repositório. Dessa forma, o serviço de autorização não precisa se preocupar com revogação, pois o repositório tem apenas certificados válidos. Esse modelo é mais adequado para ambientes nos quais os privilégios dos clientes são definidos e atribuídos no próprio domínio do servidor. A AA, em geral, está localizada no mesmo domínio.

pull

De posse dos CAs, o serviço de autorização faz as mesmas validações que um serviço de autenticação faz baseado no PKC: valida a data de expiração contra um atributo do próprio certificado e depois valida a revogação contra a LCR ou o OCSP.

Os CAs precisam ser modelados para representar o domínio do dispositivo e atender as necessidades do negócio. Pode-se utilizar algum modelo de referência, como o Controle de Acesso Baseado em Regras (do inglês, Role-Based Access Control – RBAC), onde as permissões são associadas à regras e o usuários recebem as regras apropriadas de acordo com seus papéis em um sistema, o que simplifica o gerenciamento das permissões. Uma regra serve de base para as políticas de controle de acesso. Pode-se, por exemplo, criar uma regra que agrega as permissões de um usuário padrão de uma rede e outra regra para o Administrador [10].

O X.509 delega para os serviços a decisão de dizer o que é acessado e por quais privilégios. Para auxiliar na modelagem dos privilégios, o X.509 dá suporte ao RBAC [2]:

  • Simples: são certificados de atributo de definição de regras que contém as permissões atribuídas a cada regra e certificados de atributos de atribuição de regras que atribuem as regras aos dispositivos. Trata-se de um modelo centrado em perfis de acesso e suas permissões. Os serviços de autorização devem utilizar esses perfis para realizar a autorização;
  • Hierárquico: as regras são organizadas hierarquicamente de modo que regras superiores herdam os privilégios atribuídos às regras inferiores. No X.509, regras podem ter outras regras como atributos;
  • Restrito: permite que várias restrições sejam aplicadas às regras e atribuições de permissões. Um exemplo de aplicação é para papéis mutuamente exclusivos – um dispositivo só pode ser associado a um papel em um conjunto de papéis mutuamente exclusivos;
  • Consolidado: combina os modelos hierárquico e restrito para impor limitações à hierarquia de papéis.

Resultados e Discussões

Para tornar a IoT mais segura contra aqueles que têm intenções maliciosas, deve-se investir em técnicas de criptografia que dificultem o roubo e o compartilhamento de dados, técnicas que melhorem a autenticação e mecanismos de controle de acesso autoconfiguráveis e granulares [12] como explicado aqui.

O PKC foi projetado para representar identidades em esquemas multiplataforma e multidomínios. Ele liga o identificador de uma entidade a uma chave pública gerada a partir de um algoritmo criptográfico assimétrico e sua autenticidade é garantida por um terceiro confiável – a AC. Sendo assim, ele pode ser utilizado em serviços de autenticação padronizados. Ele também resolve o problema da criptografia da comunicação, pois utiliza o conceito de chaves pública e privada: uma é utilizada para criptografar e a outra para decriptografar uma mensagem.

A revogação de um PKC pode ser verificada de forma mais eficaz através da combinação da CRL e do OCSP em um mecanismo de autenticação: primeiro, o serviço de autenticação faz a consulta contra o OCSP; caso o OCSP esteja indisponível, o serviço faz o download da CRL para a verificação local.

Um PKC não é flexível o bastante para lidar com atributos. Como exemplo, suponhamos que a autorização de um relógio “inteligente” que dentre outras capacidades acessa um serviço que faz geolocalização seja desenvolvido com base em PKC. O PKC emitido para esse dispositivo terá que ter um campo com o atributo referente à capacidade de geolocalização. Para revogar apenas essa capacidade, seria necessário revogar o próprio certificado, pois qualquer alteração em seu estado interno causaria perda da integridade.

Seria viável utilizar PKCs na IoT se fosse possível saber quais serão todas as capacidades de todos os dispositivos, garantir que esses atributos não possam ser revogados separadamente do PKC e que terão a mesma validade do PKC. A implicação é que PKCs seriam projetados para não expirar ou seriam reemitidos pelos fabricantes em um espaço de tempo muito curto, o que geraria um ônus para suas infraestruturas – eles teriam que ser capazes de gerenciar muitos certificados em um tempo aceitável.

Ao adotar um padrão para autorização garante-se a interoperabilidade entre os dispositivos, pois se não fosse assim, cada fabricante criaria um mecanismo de autorização válido apenas para seus dispositivos em seus domínios. As limitações do PKC incentivam o desenvolvimento de serviços de autorização locais, o que acaba impactando na interoperabilidade dos dispositivos e interoperabilidade é um pressuposto da IoT.

Em muitos contextos, a identidade do dispositivo não é o critério utilizado para decisões de controle de acesso, mas as informações de autorização precisam estar relacionadas a uma identidade. O propósito principal de um PKC é a autenticação, mas a autenticação não é suficiente para se determinar quem pode fazer o quê em um dado subsistema [2]. Os CAs estabelecem uma separação clara entre autenticação e autorização [4] e tornam o processo de autorização mais granular e, portanto, mais flexível.

De posse dos CAs, o serviço de autorização faz as mesmas validações que um serviço de autenticação faz baseado no PKC: valida a data de expiração contra um atributo do próprio certificado e depois valida a revogação contra a CRL ou o OCSP.

Os CAs precisam ser modelados para representarem o domínio do negócio materializado no dispositivo. Pode-se utilizar o modelo RBAC, onde as permissões são associadas às regras e os usuários recebem as regras apropriadas de acordo com seus papéis em um sistema, o que simplifica o gerenciamento das permissões.

O X.509 delega para os serviços a decisão de dizer o que é acessado e por quais privilégios. Um mecanismo de autorização baseado em CA com RBAC e um modelo de distribuição de atributos pode ser aplicado, por exemplo, para autorizar um relógio “inteligente” a dar partida em um carro “inteligente”. O appliance (dispositivo de hardware com software escrito especificamente para ele) do relógio recebe os atributos diretamente da AA utilizando distribuição push, pois são domínios diferentes, e os envia para o servidor do carro, que valida os atributos e autoriza as ações do relógio.

É possível utilizar esse mecanismo para fazer as atualizações de software, pois esse também é um caso de comunicação M2M. O fabricante pode ter um atributo que lhe autoriza a enviar as atualizações para correção de vulnerabilidades. O servidor recebe os atributos válidos diretamente do repositório da AA utilizando a distribuição pull, pois é o mesmo domínio, e se autentica no appliance. O serviço de autorização do appliance verifica os atributos do fabricante e autoriza a recepção da atualização.

Conclusão

A IoT trouxe uma nova realidade nas relações entre as pessoas e os objetos do cotidiano. Com a aplicação desse conceito, uma cidade inteligente poderia antecipar e agir autonomamente à falta d’água que ocorreu na cidade de São Paulo em 2015.

As perspectivas de negócios e o fim da limitação de endereços IP que o IPv6 proporcionou provam que a IoT crescerá até atingir dezenas de bilhões de dispositivos conectados na próxima década. Por esse motivo, questões relacionadas a padrões e em especial padrões ligados à segurança se tornam críticas para o sucesso.

A utilização de PKC padroniza e aumenta a segurança na autenticação de dispositivos e também pode ser utilizado para criptografar a comunicação utilizando o conceito de chaves pública e privada. Embora PKCs possam ser utilizados, eles não são ideias para a construção de um serviço de autorização, pois para incluir ou remover um atributo seria necessário reemitir ou revogar o próprio certificado.

Um CA traz a granularidade que falta ao PKC, mas para que possa ser utilizado deve-se escolher um modelo de divulgação de atributos – push para o mesmo domínio e pull para domínios diferentes. Os atributos devem ser modelados de acordo com o RBAC para construir uma solução flexível. O RBAC simples pode ser utilizado para compor perfis e dar suporte às políticas de autorização associadas aos dispositivos.

Para validação, o CA similar ao PKC: é emitido por um terceiro confiável – nesse caso a AA e não a AC – responsável por gerenciá-lo e os serviços de autorização podem utilizar o OCSP, a CRL e informações contidas no próprio certificado para validá-lo.

Com um CA, um mecanismo de divulgação dos atributos, a modelagem dos atributos com RBAC e a possibilidade de verificação da autenticidade e da validade dos atributos, é possível construir um mecanismo de autorização padronizado, flexível e seguro para a comunicação entre dispositivos na Internet das Coisas.

Referências

[1] Boswarthicks, O.; Elloumi, O.; Hersent, O. M2M Communications: A System Approach. 1.ed. Reino Unido: John Wiley e Sons Ltd, 2012. p. 2, 233 e 236.

[2] Chadwick, D; Otenko, A. Implementing Role Based Access Controls using X.509 Privilege Management – the PERMIS Authorisation Infrastructure. IS Institute, University of Salford, M5 4WT, England. Disponível em: [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.400.5794&rep=rep1&type=pdf]. Acesso em: 20 dez. 2014.

[3] Cooper, D. et al. Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. IETF, 2008. Disponível em: [http://www.ietf.org/rfc/rfc5280.txt]. Acesso em: 20 dez. 2014.

[4] Farrel, S; Housley, R. An Internet Attribute Certificate Profile for Authorization. IETF, 2002. Disponível em: [http://www.ietf.org/rfc/rfc3281.txt]. Acesso em: 20 dez. 2014.

[5] GRAAF, Jeroen van de.; CARVALHO, Osvaldo. Reflecting on X.509 and LDAP, or
How separating identity and attributes could simplify a PKI. Disponível em:
[http://www.redes.unb.br/ceseg/anais/2004/2957.pdf]. Acesso em: 20 dez. 2014.

[6] IERC – European Research Cluster on the Internet of Things. Internet of Things – From Research and Innovation to Market Deployment. River Publishers, 2013. p. 90-92. Disponível em: [http://www.internet-of-things-research.eu/pdf/IERC_Cluster_Book_2014_Ch.3_SRIA_WEB.pdf]. Acesso em: 24 dez. 2014.

[7] ITU. Information technology – Open systems interconnection – The Directory: Public-key and attribute certificate frameworks. ITU, 2012. p. 14, 16, 19 e 21. Disponível em: [http://www.ietf.org/mail-archive/web/wpkops/current/pdf9ygpIVtdwl.pdf]. Acesso em: 23 dez. 2014.

[8] ITU. NGN identity management framework. ITU, 2009. p. 2, 15, 19-20. Disponível em: [http://www.itu.int/rec/T-REC-Y.2720-200901-I]. Acesso em: 15 jan. 2015.

[9] Myers, M. et al. X.509 Internet Public Key Infrastructure Online Certificate Status Protocol – OCSP. IETF, 1999. Disponível em: [http://www.ietf.org/rfc/rfc2560.txt]. Acesso em: 23 dez. 2014.

[10] Sandhu, Ravi S.; Coyne, Edward J.; Feinstein, Hal L.; Youman, Charles E. Role-Based Access Control Models. IEEE Comput. 29, 1996.

[11] Schukat, M. Securing Critical Infrastructure. OSNA Cyber Security Research Group Discipline of IT National University of Ireland, Galway. Disponível em: [http://www.osna-solutions.com/wp-content/uploads/Securing-Critical-Infrastructure-Paper.pdf]. Acesso em: 23 dez. 2014.

[12] VERMESAN, Ovidiu; FRIESS, Peter. From Research and Innovation to Market
Deployment. Denmark: River Publishers, 2014. p. 7-8, 90-92. Disponível em:
[http://www.internet-of-things-
research.eu/pdf/IERC_Cluster_Book_2014_Ch.3_SRIA_WEB.pdf]. Acesso em: 24
dez. 2014.

[13] ZYTRAX. Survival guides – TLS/SSL and SSL (X.509) Certificates. Disponível em: [http://www.zytrax.com/tech/survival/ssl.html]. Acesso em: 5 jan. 2015.