feat: implement security enhancements for Jitsi integration, including JWT token generation and automatic blocking of detected attacks, improving system resilience and user authentication
This commit is contained in:
526
scripts/configurar-jitsi.sh
Executable file
526
scripts/configurar-jitsi.sh
Executable file
@@ -0,0 +1,526 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de configuração interativa do Jitsi Meet para SGSE
|
||||
# Este script facilita a configuração inicial do Jitsi no sistema SGSE
|
||||
|
||||
set -e
|
||||
|
||||
# Cores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Variáveis
|
||||
DOMAIN=""
|
||||
APP_ID=""
|
||||
ROOM_PREFIX=""
|
||||
USE_HTTPS=false
|
||||
ACCEPT_SELF_SIGNED=false
|
||||
JWT_SECRET=""
|
||||
JWT_AUDIENCE=""
|
||||
JWT_ISSUER=""
|
||||
AMBIENTE=""
|
||||
TEST_ONLY=false
|
||||
VALIDATE_ONLY=false
|
||||
NON_INTERACTIVE=false
|
||||
|
||||
# Função para imprimir mensagens
|
||||
print_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# Função para validar formato de domínio
|
||||
validar_dominio() {
|
||||
local dominio=$1
|
||||
if [[ -z "$dominio" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Padrão para localhost:porta
|
||||
if [[ $dominio =~ ^(localhost|127\.0\.0\.1|0\.0\.0\.0)(:[0-9]+)?$ ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Padrão para FQDN
|
||||
if [[ $dominio =~ ^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(:[0-9]+)?$ ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Função para validar App ID
|
||||
validar_app_id() {
|
||||
local app_id=$1
|
||||
if [[ -z "$app_id" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ $app_id =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Função para validar JWT Secret
|
||||
validar_jwt_secret() {
|
||||
local secret=$1
|
||||
if [[ -z "$secret" ]]; then
|
||||
return 0 # Opcional
|
||||
fi
|
||||
|
||||
if [[ ${#secret} -lt 16 ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Função para testar conectividade
|
||||
testar_conectividade() {
|
||||
local dominio=$1
|
||||
local use_https=$2
|
||||
|
||||
print_info "Testando conectividade com $dominio..."
|
||||
|
||||
# Extrair host e porta
|
||||
local host=$(echo $dominio | cut -d: -f1)
|
||||
local porta=$(echo $dominio | cut -d: -f2)
|
||||
|
||||
if [[ -z "$porta" ]]; then
|
||||
if [[ "$use_https" == "true" ]]; then
|
||||
porta=443
|
||||
else
|
||||
porta=80
|
||||
fi
|
||||
fi
|
||||
|
||||
local protocol="http"
|
||||
if [[ "$use_https" == "true" ]]; then
|
||||
protocol="https"
|
||||
fi
|
||||
|
||||
local url="$protocol://$host:$porta/http-bind"
|
||||
|
||||
# Testar conexão
|
||||
if command -v curl &> /dev/null; then
|
||||
local response=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$url" 2>&1 || echo "000")
|
||||
if [[ "$response" == "200" ]] || [[ "$response" == "405" ]] || [[ "$response" == "000" ]]; then
|
||||
# 405 é esperado (Method Not Allowed para GET em /http-bind)
|
||||
print_success "Servidor acessível em $url"
|
||||
return 0
|
||||
else
|
||||
print_warning "Servidor retornou status $response (pode ser normal para /http-bind)"
|
||||
return 0
|
||||
fi
|
||||
elif command -v wget &> /dev/null; then
|
||||
if wget --spider --timeout=10 "$url" 2>&1 | grep -q "200 OK\|405\|connected"; then
|
||||
print_success "Servidor acessível em $url"
|
||||
return 0
|
||||
else
|
||||
print_warning "Não foi possível verificar conectividade (wget)"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_warning "curl ou wget não encontrado. Pulando teste de conectividade."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Função para validar certificado SSL
|
||||
validar_certificado_ssl() {
|
||||
local dominio=$1
|
||||
|
||||
if [[ ! "$dominio" =~ ^localhost ]]; then
|
||||
print_info "Validando certificado SSL para $dominio..."
|
||||
|
||||
local host=$(echo $dominio | cut -d: -f1)
|
||||
local porta=$(echo $dominio | cut -d: -f2)
|
||||
|
||||
if [[ -z "$porta" ]]; then
|
||||
porta=443
|
||||
fi
|
||||
|
||||
if command -v openssl &> /dev/null; then
|
||||
local cert_info=$(echo | openssl s_client -connect "$host:$porta" -servername "$host" 2>&1 | grep -A 2 "Certificate chain\|Verify return code")
|
||||
if echo "$cert_info" | grep -q "Verify return code: 0"; then
|
||||
print_success "Certificado SSL válido"
|
||||
return 0
|
||||
else
|
||||
print_warning "Certificado SSL não válido ou autoassinado"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_warning "openssl não encontrado. Pulando validação de certificado."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Função para gerar JWT Secret
|
||||
gerar_jwt_secret() {
|
||||
if command -v openssl &> /dev/null; then
|
||||
openssl rand -hex 32
|
||||
elif [[ -r /dev/urandom ]]; then
|
||||
head -c 32 /dev/urandom | base64 | tr -d '\n' | head -c 64
|
||||
else
|
||||
print_error "Não foi possível gerar JWT Secret. Instale openssl ou forneça manualmente."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Função para ler entrada do usuário
|
||||
ler_entrada() {
|
||||
local prompt=$1
|
||||
local default=$2
|
||||
local var_name=$3
|
||||
|
||||
if [[ "$NON_INTERACTIVE" == "true" ]]; then
|
||||
if [[ -n "$default" ]]; then
|
||||
eval "$var_name='$default'"
|
||||
return
|
||||
else
|
||||
print_error "Modo não-interativo requer valor para: $prompt"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local input
|
||||
if [[ -n "$default" ]]; then
|
||||
read -p "$(echo -e ${BLUE}$prompt${NC} [padrão: $default]): " input
|
||||
eval "$var_name=\${input:-$default}"
|
||||
else
|
||||
read -p "$(echo -e ${BLUE}$prompt${NC}): " input
|
||||
eval "$var_name='$input'"
|
||||
fi
|
||||
}
|
||||
|
||||
# Função para exibir ajuda
|
||||
mostrar_ajuda() {
|
||||
cat << EOF
|
||||
Uso: $0 [OPÇÕES]
|
||||
|
||||
Script de configuração interativa do Jitsi Meet para SGSE.
|
||||
|
||||
OPÇÕES:
|
||||
--ambiente NOME Especificar ambiente (desenvolvimento, staging, producao)
|
||||
--domain DOMINIO Configurar domínio do servidor Jitsi
|
||||
--app-id ID Configurar App ID
|
||||
--jwt-secret SECRET Configurar JWT Secret (ou gerar automaticamente se não fornecido)
|
||||
--room-prefix PREFIXO Configurar prefixo de sala
|
||||
--use-https Usar HTTPS
|
||||
--accept-self-signed Aceitar certificados autoassinados
|
||||
--test-only Apenas testar configuração existente
|
||||
--validate-only Apenas validar sem salvar
|
||||
--non-interactive Modo não-interativo (para CI/CD)
|
||||
--help Mostrar esta ajuda
|
||||
|
||||
EXEMPLOS:
|
||||
# Modo interativo
|
||||
$0
|
||||
|
||||
# Modo não-interativo
|
||||
$0 --domain meet.example.com --app-id sgse-app --use-https
|
||||
|
||||
# Apenas validar
|
||||
$0 --validate-only --domain meet.example.com
|
||||
|
||||
# Apenas testar
|
||||
$0 --test-only
|
||||
EOF
|
||||
}
|
||||
|
||||
# Processar argumentos da linha de comando
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--ambiente)
|
||||
AMBIENTE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--domain|--domínio)
|
||||
DOMAIN="$2"
|
||||
shift 2
|
||||
;;
|
||||
--app-id)
|
||||
APP_ID="$2"
|
||||
shift 2
|
||||
;;
|
||||
--jwt-secret)
|
||||
JWT_SECRET="$2"
|
||||
shift 2
|
||||
;;
|
||||
--room-prefix)
|
||||
ROOM_PREFIX="$2"
|
||||
shift 2
|
||||
;;
|
||||
--use-https)
|
||||
USE_HTTPS=true
|
||||
shift
|
||||
;;
|
||||
--accept-self-signed)
|
||||
ACCEPT_SELF_SIGNED=true
|
||||
shift
|
||||
;;
|
||||
--test-only)
|
||||
TEST_ONLY=true
|
||||
shift
|
||||
;;
|
||||
--validate-only)
|
||||
VALIDATE_ONLY=true
|
||||
shift
|
||||
;;
|
||||
--non-interactive)
|
||||
NON_INTERACTIVE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
mostrar_ajuda
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "Opção desconhecida: $1"
|
||||
mostrar_ajuda
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Banner
|
||||
echo -e "${BLUE}"
|
||||
cat << "EOF"
|
||||
╔═══════════════════════════════════════════════════════════╗
|
||||
║ Configuração do Jitsi Meet para SGSE ║
|
||||
╚═══════════════════════════════════════════════════════════╝
|
||||
EOF
|
||||
echo -e "${NC}"
|
||||
|
||||
# Modo apenas teste
|
||||
if [[ "$TEST_ONLY" == "true" ]]; then
|
||||
print_info "Modo de teste apenas. Validando configuração existente..."
|
||||
# Aqui você pode adicionar lógica para testar configuração existente
|
||||
# Por exemplo, buscar do banco de dados ou arquivo de configuração
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Coletar informações
|
||||
if [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
print_info "Coletando informações de configuração..."
|
||||
echo
|
||||
fi
|
||||
|
||||
# Ambiente
|
||||
if [[ -z "$AMBIENTE" ]]; then
|
||||
ler_entrada "Ambiente (desenvolvimento, staging, producao)" "" AMBIENTE
|
||||
fi
|
||||
|
||||
# Domínio
|
||||
while [[ -z "$DOMAIN" ]] || ! validar_dominio "$DOMAIN"; do
|
||||
if [[ -z "$DOMAIN" ]]; then
|
||||
ler_entrada "Domínio do servidor Jitsi (ex: localhost:8443 ou meet.example.com)" "" DOMAIN
|
||||
else
|
||||
print_error "Domínio inválido: $DOMAIN"
|
||||
DOMAIN=""
|
||||
ler_entrada "Domínio do servidor Jitsi" "" DOMAIN
|
||||
fi
|
||||
done
|
||||
|
||||
# Detectar HTTPS automaticamente
|
||||
if [[ "$DOMAIN" =~ :8443$ ]] || [[ "$DOMAIN" =~ ^[^:]+$ ]] && [[ ! "$DOMAIN" =~ ^localhost ]]; then
|
||||
if [[ "$USE_HTTPS" != "true" ]] && [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
read -p "$(echo -e ${BLUE}Usar HTTPS? (S/n)${NC}): " resposta
|
||||
if [[ "$resposta" =~ ^[Ss]$ ]] || [[ -z "$resposta" ]]; then
|
||||
USE_HTTPS=true
|
||||
fi
|
||||
elif [[ -z "$USE_HTTPS" ]]; then
|
||||
USE_HTTPS=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Aceitar certificados autoassinados
|
||||
if [[ "$USE_HTTPS" == "true" ]] && [[ "$DOMAIN" =~ localhost ]]; then
|
||||
if [[ "$ACCEPT_SELF_SIGNED" != "true" ]] && [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
read -p "$(echo -e ${BLUE}Aceitar certificados autoassinados? (S/n)${NC}): " resposta
|
||||
if [[ "$resposta" =~ ^[Ss]$ ]] || [[ -z "$resposta" ]]; then
|
||||
ACCEPT_SELF_SIGNED=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# App ID
|
||||
while [[ -z "$APP_ID" ]] || ! validar_app_id "$APP_ID"; do
|
||||
if [[ -z "$APP_ID" ]]; then
|
||||
ler_entrada "App ID" "sgse-app" APP_ID
|
||||
else
|
||||
print_error "App ID inválido: $APP_ID (deve conter apenas letras, números, hífens e underscores)"
|
||||
APP_ID=""
|
||||
ler_entrada "App ID" "sgse-app" APP_ID
|
||||
fi
|
||||
done
|
||||
|
||||
# Room Prefix
|
||||
if [[ -z "$ROOM_PREFIX" ]]; then
|
||||
ler_entrada "Prefixo de sala" "sgse" ROOM_PREFIX
|
||||
fi
|
||||
|
||||
# JWT Secret
|
||||
if [[ -z "$JWT_SECRET" ]]; then
|
||||
if [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
read -p "$(echo -e ${BLUE}Gerar JWT Secret automaticamente? (S/n)${NC}): " resposta
|
||||
if [[ "$resposta" =~ ^[Ss]$ ]] || [[ -z "$resposta" ]]; then
|
||||
JWT_SECRET=$(gerar_jwt_secret)
|
||||
print_success "JWT Secret gerado: ${JWT_SECRET:0:16}..."
|
||||
else
|
||||
ler_entrada "JWT Secret (deixe vazio para desabilitar JWT)" "" JWT_SECRET
|
||||
fi
|
||||
else
|
||||
JWT_SECRET=$(gerar_jwt_secret)
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validar JWT Secret se fornecido
|
||||
if [[ -n "$JWT_SECRET" ]] && ! validar_jwt_secret "$JWT_SECRET"; then
|
||||
print_error "JWT Secret deve ter no mínimo 16 caracteres"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# JWT Audience (opcional)
|
||||
if [[ -z "$JWT_AUDIENCE" ]] && [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
ler_entrada "JWT Audience (opcional, padrão: domínio)" "$DOMAIN" JWT_AUDIENCE
|
||||
fi
|
||||
|
||||
# JWT Issuer (opcional)
|
||||
if [[ -z "$JWT_ISSUER" ]] && [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
ler_entrada "JWT Issuer (opcional, padrão: App ID)" "$APP_ID" JWT_ISSUER
|
||||
fi
|
||||
|
||||
# Validações
|
||||
print_info "Validando configuração..."
|
||||
|
||||
# Validar domínio
|
||||
if ! validar_dominio "$DOMAIN"; then
|
||||
print_error "Domínio inválido: $DOMAIN"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validar App ID
|
||||
if ! validar_app_id "$APP_ID"; then
|
||||
print_error "App ID inválido: $APP_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validar JWT Secret
|
||||
if [[ -n "$JWT_SECRET" ]] && ! validar_jwt_secret "$JWT_SECRET"; then
|
||||
print_error "JWT Secret inválido (mínimo 16 caracteres)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_success "Validações básicas passaram"
|
||||
|
||||
# Testes de conectividade
|
||||
if [[ "$VALIDATE_ONLY" != "true" ]]; then
|
||||
print_info "Testando conectividade..."
|
||||
if testar_conectividade "$DOMAIN" "$USE_HTTPS"; then
|
||||
print_success "Conectividade OK"
|
||||
else
|
||||
print_warning "Não foi possível testar conectividade (servidor pode estar offline)"
|
||||
fi
|
||||
|
||||
# Validar certificado SSL se HTTPS
|
||||
if [[ "$USE_HTTPS" == "true" ]]; then
|
||||
validar_certificado_ssl "$DOMAIN"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Resumo
|
||||
echo
|
||||
print_info "Resumo da configuração:"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Ambiente: ${AMBIENTE:-padrão}"
|
||||
echo " Domínio: $DOMAIN"
|
||||
echo " App ID: $APP_ID"
|
||||
echo " Prefixo de Sala: $ROOM_PREFIX"
|
||||
echo " HTTPS: $USE_HTTPS"
|
||||
echo " Cert. Autoassinado: $ACCEPT_SELF_SIGNED"
|
||||
if [[ -n "$JWT_SECRET" ]]; then
|
||||
echo " JWT Secret: ${JWT_SECRET:0:16}... (${#JWT_SECRET} caracteres)"
|
||||
else
|
||||
echo " JWT Secret: (não configurado)"
|
||||
fi
|
||||
if [[ -n "$JWT_AUDIENCE" ]]; then
|
||||
echo " JWT Audience: $JWT_AUDIENCE"
|
||||
fi
|
||||
if [[ -n "$JWT_ISSUER" ]]; then
|
||||
echo " JWT Issuer: $JWT_ISSUER"
|
||||
fi
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# Se apenas validar, sair aqui
|
||||
if [[ "$VALIDATE_ONLY" == "true" ]]; then
|
||||
print_success "Validação concluída"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Confirmar antes de salvar
|
||||
if [[ "$NON_INTERACTIVE" != "true" ]]; then
|
||||
echo
|
||||
read -p "$(echo -e ${BLUE}Salvar esta configuração? (S/n)${NC}): " confirmar
|
||||
if [[ ! "$confirmar" =~ ^[Ss]$ ]] && [[ -n "$confirmar" ]]; then
|
||||
print_info "Configuração cancelada pelo usuário"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Gerar JSON de configuração
|
||||
CONFIG_JSON=$(cat <<EOF
|
||||
{
|
||||
"domain": "$DOMAIN",
|
||||
"appId": "$APP_ID",
|
||||
"roomPrefix": "$ROOM_PREFIX",
|
||||
"useHttps": $USE_HTTPS,
|
||||
"acceptSelfSignedCert": $ACCEPT_SELF_SIGNED,
|
||||
"ambiente": "${AMBIENTE:-}",
|
||||
"jwtSecret": "${JWT_SECRET:-}",
|
||||
"jwtAudience": "${JWT_AUDIENCE:-}",
|
||||
"jwtIssuer": "${JWT_ISSUER:-}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Salvar em arquivo
|
||||
CONFIG_FILE="jitsi-config-$(date +%Y%m%d-%H%M%S).json"
|
||||
echo "$CONFIG_JSON" > "$CONFIG_FILE"
|
||||
print_success "Configuração salva em: $CONFIG_FILE"
|
||||
|
||||
# Instruções finais
|
||||
echo
|
||||
print_info "Próximos passos:"
|
||||
echo "1. Revise o arquivo de configuração: $CONFIG_FILE"
|
||||
echo "2. Acesse o painel SGSE: TI > Configurações do Jitsi"
|
||||
echo "3. Preencha os campos com os valores acima"
|
||||
echo "4. Teste a conexão usando o botão 'Testar Conexão'"
|
||||
echo "5. Salve a configuração no painel"
|
||||
|
||||
if [[ -n "$JWT_SECRET" ]]; then
|
||||
echo
|
||||
print_warning "IMPORTANTE: Guarde o JWT Secret em local seguro!"
|
||||
print_warning "O JWT Secret não será exibido novamente."
|
||||
fi
|
||||
|
||||
print_success "Configuração concluída!"
|
||||
Reference in New Issue
Block a user