Pular para o conteúdo principal

Segurança do Sistema

Visão Geral de Segurança

O Acesso ao Emprego implementa medidas de segurança em múltiplas camadas, seguindo as melhores práticas para proteção de dados e privacidade dos usuários.

Arquitetura de Segurança Implementada

Princípios de Segurança Adotados

  1. Defesa em Profundidade: Múltiplas camadas de proteção
  2. Princípio do Menor Privilégio: Acesso mínimo necessário
  3. Separação de Responsabilidades: Isolamento de componentes
  4. Falha Segura: Sistema falha de forma controlada
  5. Conformidade LGPD: Proteção de dados pessoais

Camadas de Segurança

Aplicação:

  • Autenticação JWT
  • Validação de entrada
  • Proteção CSRF
  • Rate limiting básico

Dados:

  • Criptografia de senhas
  • Validação de CPF/email
  • Sanitização de inputs
  • Backup regular

Infraestrutura:

  • HTTPS obrigatório
  • Containers isolados
  • Secrets management
  • Logs de auditoria

Autenticação e Autorização

Sistema de Autenticação JWT

Implementação Atual:

# authentication.py
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate

class AuthenticationService:
"""Serviço de autenticação com JWT"""

@staticmethod
def login(email, password):
"""Autenticação de usuário"""
user = authenticate(email=email, password=password)

if user and user.is_active:
refresh = RefreshToken.for_user(user)

return {
'refresh': str(refresh),
'access': str(refresh.access_token),
'user': {
'id': user.id,
'email': user.email,
'is_candidate': user.is_candidate,
'is_company': user.is_company,
'is_government_agent': user.is_government_agent
}
}

return None

@staticmethod
def refresh_token(refresh_token):
"""Renovação de token de acesso"""
try:
refresh = RefreshToken(refresh_token)
return {
'access': str(refresh.access_token)
}
except Exception:
return None

Configuração de Tokens:

# settings.py
from datetime import timedelta

SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': True,

'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,

'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',

'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
}

Sistema de Permissões

Permissões Baseadas em Roles:

# permissions.py
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
"""Permite edição apenas para o proprietário"""

def has_object_permission(self, request, view, obj):
# Leitura permitida para todos
if request.method in permissions.SAFE_METHODS:
return True

# Escrita apenas para o proprietário
return obj.user == request.user

class IsCandidateUser(permissions.BasePermission):
"""Permite acesso apenas para candidatos"""

def has_permission(self, request, view):
return request.user and request.user.is_candidate

class IsCompanyUser(permissions.BasePermission):
"""Permite acesso apenas para empresas"""

def has_permission(self, request, view):
return request.user and request.user.is_company

class IsGovernmentAgent(permissions.BasePermission):
"""Permite acesso apenas para agentes governamentais"""

def has_permission(self, request, view):
return request.user and request.user.is_government_agent

Proteção de Dados

Validação e Sanitização

Validação de Dados Sensíveis:

# validators.py
import re
from django.core.exceptions import ValidationError

def validate_cpf(value):
"""Valida CPF brasileiro"""
# Remove caracteres não numéricos
cpf = re.sub(r'\D', '', value)

if len(cpf) != 11:
raise ValidationError('CPF deve conter 11 dígitos')

# Verifica se todos os dígitos são iguais
if cpf == cpf[0] * 11:
raise ValidationError('CPF inválido')

# Calcula o primeiro dígito verificador
soma = sum(int(cpf[i]) * (10 - i) for i in range(9))
digito1 = 11 - (soma % 11)
if digito1 >= 10:
digito1 = 0

# Calcula o segundo dígito verificador
soma = sum(int(cpf[i]) * (11 - i) for i in range(10))
digito2 = 11 - (soma % 11)
if digito2 >= 10:
digito2 = 0

# Verifica os dígitos verificadores
if cpf[-2:] != f"{digito1}{digito2}":
raise ValidationError('CPF inválido')

return cpf

def sanitize_input(text):
"""Remove caracteres perigosos de entrada de texto"""
if not text:
return text

# Remove tags HTML/JavaScript
text = re.sub(r'<[^>]*>', '', text)
text = re.sub(r'javascript:', '', text, flags=re.IGNORECASE)

# Remove caracteres de controle
text = ''.join(char for char in text if ord(char) >= 32)

return text.strip()

Criptografia de Senhas

Configuração Django:

# settings.py
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 8,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]

Segurança da API

Rate Limiting

Implementação com Django Ratelimit:

# views.py
from django_ratelimit.decorators import ratelimit
from rest_framework.decorators import api_view

@api_view(['POST'])
@ratelimit(key='ip', rate='5/m', method='POST') # 5 tentativas por minuto
def login(request):
"""Endpoint de login com rate limiting"""
# Lógica de autenticação
pass

@api_view(['GET'])
@ratelimit(key='user', rate='100/h') # 100 requisições por hora para usuários autenticados
def list_jobs(request):
"""Listagem de vagas com rate limiting"""
# Lógica de listagem
pass

Proteção CSRF

# settings.py
CSRF_COOKIE_SECURE = True # Apenas HTTPS em produção
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SAMESITE = 'Strict'
CSRF_TRUSTED_ORIGINS = [
'https://portal-talentos.gov.br',
'https://www.portal-talentos.gov.br',
]

# Em produção
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Strict'

Headers de Segurança

# middleware.py
class SecurityHeadersMiddleware:
"""Adiciona headers de segurança às respostas"""

def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
response = self.get_response(request)

# Headers de segurança
response['X-Content-Type-Options'] = 'nosniff'
response['X-Frame-Options'] = 'DENY'
response['X-XSS-Protection'] = '1; mode=block'
response['Referrer-Policy'] = 'strict-origin-when-cross-origin'

# HSTS em produção
if not settings.DEBUG:
response['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'

return response

Logs e Auditoria

Sistema de Logs

# logging_config.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'security': {
'format': '{asctime} SECURITY [{levelname}] {message}',
'style': '{',
},
},
'handlers': {
'security_file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/portal_talentos/security.log',
'maxBytes': 1024 * 1024 * 10, # 10 MB
'backupCount': 10,
'formatter': 'security',
},
'audit_file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/portal_talentos/audit.log',
'maxBytes': 1024 * 1024 * 10, # 10 MB
'backupCount': 30,
'formatter': 'verbose',
},
},
'loggers': {
'security': {
'handlers': ['security_file'],
'level': 'INFO',
'propagate': False,
},
'audit': {
'handlers': ['audit_file'],
'level': 'INFO',
'propagate': False,
},
},
}

Auditoria de Ações

# audit.py
import logging
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.dispatch import receiver

audit_logger = logging.getLogger('audit')
security_logger = logging.getLogger('security')

@receiver(user_logged_in)
def log_user_login(sender, request, user, **kwargs):
"""Registra login bem-sucedido"""
audit_logger.info(
f"Login successful - User: {user.email}, "
f"IP: {get_client_ip(request)}, "
f"User-Agent: {request.META.get('HTTP_USER_AGENT')}"
)

@receiver(user_login_failed)
def log_user_login_failed(sender, credentials, request, **kwargs):
"""Registra tentativa de login falhada"""
security_logger.warning(
f"Login failed - Username: {credentials.get('username')}, "
f"IP: {get_client_ip(request)}, "
f"User-Agent: {request.META.get('HTTP_USER_AGENT')}"
)

def get_client_ip(request):
"""Obtém o IP real do cliente"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip

Conformidade LGPD

Implementações para LGPD

# lgpd_compliance.py
from django.db import models
from django.utils import timezone

class ConsentRecord(models.Model):
"""Registro de consentimento LGPD"""
user = models.ForeignKey('accounts.CustomUser', on_delete=models.CASCADE)
consent_type = models.CharField(max_length=50)
granted_at = models.DateTimeField(default=timezone.now)
revoked_at = models.DateTimeField(null=True, blank=True)
ip_address = models.GenericIPAddressField()
user_agent = models.TextField()

class Meta:
db_table = 'lgpd_consent_records'

class DataExportRequest(models.Model):
"""Solicitações de exportação de dados (LGPD)"""
user = models.ForeignKey('accounts.CustomUser', on_delete=models.CASCADE)
requested_at = models.DateTimeField(default=timezone.now)
completed_at = models.DateTimeField(null=True, blank=True)
file_url = models.URLField(null=True, blank=True)
status = models.CharField(max_length=20, default='pending')

class Meta:
db_table = 'lgpd_data_export_requests'

class DataDeletionRequest(models.Model):
"""Solicitações de exclusão de dados (direito ao esquecimento)"""
user_email = models.EmailField() # Mantém email para registro
requested_at = models.DateTimeField(default=timezone.now)
processed_at = models.DateTimeField(null=True, blank=True)
status = models.CharField(max_length=20, default='pending')

class Meta:
db_table = 'lgpd_data_deletion_requests'

Segurança em Desenvolvimento Futuro

Melhorias Planejadas

Autenticação Multi-Fator (MFA):

  • Implementação de TOTP (Time-based One-Time Password)
  • Suporte a aplicativos autenticadores
  • Códigos de backup para recuperação

Monitoramento Avançado:

  • Sistema de detecção de intrusão
  • Análise comportamental de usuários
  • Alertas em tempo real para atividades suspeitas

Criptografia Aprimorada:

  • Criptografia de campos sensíveis no banco de dados
  • Tokenização de CPF e dados pessoais
  • Gerenciamento de chaves com rotação automática

Integração com Serviços Governamentais:

  • Autenticação via Gov.br (OAuth 2.0)
  • Validação de CPF com Receita Federal
  • Integração com certificados digitais

Resposta a Incidentes

Procedimento Básico

  1. Detecção: Identificação através de logs e monitoramento
  2. Contenção: Isolamento do problema para evitar propagação
  3. Investigação: Análise da causa e extensão do incidente
  4. Remediação: Correção da vulnerabilidade
  5. Recuperação: Restauração dos serviços
  6. Documentação: Registro detalhado e lições aprendidas

Contatos de Emergência

# security_contacts.py
SECURITY_TEAM = {
'email': 'security@portal-talentos.gov.br',
'phone': '+55 11 xxxx-xxxx',
'escalation': 'ciso@portal-talentos.gov.br'
}

# Configuração de alertas automáticos
SECURITY_ALERTS = {
'critical': ['security@portal-talentos.gov.br', 'ops@portal-talentos.gov.br'],
'high': ['security@portal-talentos.gov.br'],
'medium': ['security@portal-talentos.gov.br'],
}

Segurança Contínua

A segurança é um processo contínuo. Este documento reflete as implementações atuais e o roadmap de melhorias. Auditorias regulares e atualizações são essenciais para manter o sistema seguro.

Ambiente de Desenvolvimento

O sistema está em desenvolvimento ativo. Nem todas as medidas de segurança estão completamente implementadas. As configurações de produção serão mais restritivas que o ambiente de desenvolvimento.