#!/bin/bash # Por Tales A. Mendonça (talesam@gmail.com) # Faz a instalação da aplicação IHX Access Pro em Docker # Versão do script Ver="v1.8.6" # Definição de Cores CIN='\e[30;1m' # Cinza RED='\e[31;1m' # Vermelho GRE='\e[32;1m' # Verde YEL='\e[33;1m' # Amarelo BLU='\e[34;1m' # Azul ROS='\e[35;1m' # Rosa CYA='\e[36;1m' # Ciano NEG='\e[37;1m' # Negrito CUI='\e[40;31;5m' # Vermelho pisacando, aviso! STD='\e[m' # Fechamento de cor ### INÍCIO FUNÇÕES ### # Função pause pause(){ read -p "$*" } ### Função Alerta Vermelho alertaVermelho() { echo -e "${RED}*${STD} ${NEG} $1 ${STD}" echo "" } ### Função Alerta Amarelo alertaAmarelo() { echo -e "${YEL}*${STD} ${NEG} $1 ${STD}" echo "" sleep 1 } ### Função Alerta Verde alertaVerde() { echo -e "${GRE}*${STD} ${NEG} $1 ${STD}" echo "" sleep 1 } ### Função Alerta Verde alertaAzul() { echo -e "${BLU}*${STD} ${NEG} $1 ${STD}" echo "" sleep 1 } ### Função coleta de dados coletaDados() { # Este é um loop infinito que continuará até que seja quebrado com 'break' while : ; do # Solicitar entrada do usuário alertaAzul "Insira o nome do cliente:" read cliente # Definir o caminho para o diretório do cliente caminho="$HOME/Docker/IHX_Access_Pro/$cliente" # Converte a entrada do usuário para minúsculas cliente=${cliente,,} # Verificar se a entrada não está vazia if [ -z "$cliente" ]; then alertaAmarelo "O nome do cliente não pode ser vazio." else break # Se a entrada não estiver vazia, quebra o loop e continua o script fi done # Verificar se o diretório já existe if [ -d "$caminho" ]; then alertaAmarelo "Diretório $caminho já existe." else # Criar o diretório se ele não existir mkdir -p "$caminho" alertaVerde "Diretório $caminho criado com sucesso." fi # caminho para o arquivo .env envPath="$caminho/.env" # Encontra e configura a porta disponível if ! encontrarPortaDisponivel "$envPath"; then alertaVermelho "Erro ao encontrar uma porta disponível." exit 1 fi # Escrever as variáveis no arquivo .env para o docker-compose.yml { echo "cliente=$cliente" echo "db_Container_Name=db_ihx_$cliente" echo "db_Root_Password=1hx@p4550rd" echo "db_Name=ihx_access_pro" echo "db_User=db_user" echo "db_Password=1hx@p4550rd" echo "app_Container_Name=ihx_$cliente" echo "network_Name=ihx-net_$cliente" } >> "$envPath" # Carregar arquivo .env source "$envPath" } # Função para encontrar uma porta disponível encontrarPortaDisponivel() { local envPath="$1" # Adiciona um argumento para o caminho do arquivo .env local basePort=33601 # Porta base para começar a busca local maxPort=34000 # Porta máxima que queremos verificar local port=$basePort # Loop para encontrar uma porta disponível while : ; do # Checa se a porta está em uso (necessário ter o net-tools instalado) if ! netstat -tuln | grep -q ":$port"; then # Porta está disponível alertaVerde "Porta disponível encontrada: $port" # Escreve a porta disponível no arquivo .env e verifica se foi bem-sucedido echo "porta_db=$port" >> "$envPath" && \ alertaVerde "Porta escrita no arquivo .env com sucesso." || \ { alertaVermelho "Falha ao escrever a porta no arquivo .env."; return 1; } # Adiciona a regra no firewall para permitir a porta encontrada (necessário ter permissões de superusuário) if ! sudo ufw allow $port/tcp; then alertaVermelho "Falha ao adicionar regra no firewall para a porta $port." return 1 else alertaVerde "Regra no firewall adicionada com sucesso para a porta $port." return 0 fi else # Porta está em uso, incrementa e tenta a próxima ((port++)) if [ $port -ge $maxPort ]; then alertaVermelho "Não foi possível encontrar uma porta disponível." return 1 fi fi done } ### Função para baixa os arquivos necessários arquivosNecessarios() { # Diretório temporário para extração dos arquivos baixados dirTmp="/tmp/IHX" rm -rf $dirTmp # Cria o diretório temporário mkdir -p $dirTmp # Nome do arquivo arquivo="docker-compose_v1.8.tar.bz2" # Baixa o arquivo wget -q https://cloud.talesam.org/s/zekHJye2ncwM4pk/download/$arquivo -P $dirTmp # Verifica se o arquivo foi baixado corretamente if [ ! -f "$dirTmp/$arquivo" ]; then alertaVermelho "Erro: O arquivo não foi baixado corretamente." exit 1 fi # Extrai o arquivo tar -xvJf $dirTmp/$arquivo -C $caminho # Verifica se o arquivo foi extraído corretamente if [ $? -ne 0 ]; then alertaVermelho "Erro: Falha ao extrair o arquivo." exit 1 else alertaVerde "Arquivos extraídos com sucesso para $caminho." fi } ### Função para instalar aplicação IHX instalarIHX() { # Limpa a tela clear # Chama a função para coleta de dados coletaDados # Chama a funçao para baixar os arquivos arquivosNecessarios # Inicia os Conteiners alertaAzul "Ativando todos os containers, aguarde..." # Deixa os conteiners rodando em segundo plano cd $caminho docker-compose up -d && sleep 1 # Nomes dos contêineres a serem verificados containers=("$db_Container_Name") # Verifica a saúde dos contêineres for container in "${containers[@]}"; do statusSaude="" tentativasMax=100 tentativas=0 pontos="" while [[ "$statusSaude" != "healthy" && $tentativas -lt $tentativasMax ]]; do statusSaude=$(docker inspect --format='{{json .State.Health.Status}}' "$container" | tr -d '"') if [[ "$statusSaude" == "healthy" ]]; then alertaVerde "Contêiner $container saudável!" else pontos+="." printf " ${YEL}*${STD} ${NEG}Contêiner{STD} ${YEL}%-22s${STD} ${NEG}ainda está iniciando, aguardando$pontos${STD}\r" "$container" fi ((tentativas++)) sleep 1 done echo "" if [[ "$statusSaude" != "healthy" ]]; then alertaVermelho "Contêiner $container não ficou saudável após $tentativasMax tentativas." exit 1 fi # O contêiner está saudável, executar criação de tabelas alertaAzul "Iniciando a criação das tabelas e importação do banco de dados no contêiner $app_Container_Name..." docker exec $app_Container_Name bash -c "source /ihx_access_pro/env/bin/activate && python2 /ihx_access_pro/manage.py syncdb --noinput" if [[ $? -eq 0 ]]; then alertaVerde "Tabelas criadas e sincronizadas com sucesso!" sqlFileS=("funcoes.sql" "inserts.sql" "updates.sql") sucessoImportacao=true for sqlFile in "${sqlFileS[@]}"; do alertaAzul "Copiando e importando $sqlFile" docker cp $caminho/Config/db/$sqlFile $db_Container_Name:/tmp/$sqlFile docker exec $db_Container_Name mysql -u$db_User -p$db_Password ihx_access_pro -e "source /tmp/$sqlFile" if [[ $? -ne 0 ]]; then alertaVermelho "Falha ao importar $sqlFile" sucessoImportacao=false break else alertaVerde "$sqlFile importado com sucesso!" fi done else alertaVermelho "Falha ao criar tabelas ou importar banco de dados!" exit 1 fi done # Chama a função pause pause " Tecle [Enter] para voltar ao menu..." && sleep 1 ; clear } ### Função para instalar certificado SSL instalarCertificado() { # Limpa a tela clear # Listar os Diretórios baseDir="$HOME/Docker/IHX_Access_Pro/" IFS=$'\n' read -d '' -r -a dirArray < <(ls -d "$baseDir"*/ && printf '\0') # Exibir o Menu alertaAzul "Escolha onde deseja instalar o certificado SSL:" for i in "${!dirArray[@]}"; do dirName=$(basename "${dirArray[$i]}") echo -e "${BLU}$((i + 1)))${STD} $dirName" done # Adicionada a opção de voltar echo -e "${ROS}$(( ${#dirArray[@]} + 1 )))${STD} Voltar ao menu principal" # Seleção do Usuário echo "" read -p "Escolha um número: " choice # Se o usuário escolher 'Voltar ao menu principal' if [ "$choice" -eq "$(( ${#dirArray[@]} + 1 ))" ]; then return fi cliente=$(basename "${dirArray[$((choice - 1))]}") # Define o caminho para o diretório do cliente caminho="$HOME/Docker/IHX_Access_Pro/$cliente" # Desativando contêineres para gerar e importar das chaves e certificados SSL alertaAzul "Desativando os contêineres para gerar e importar as chaves e certificados SSL, aguarde..." if ! cd "$caminho" || ! docker-compose down; then alertaVermelho "Falha ao desativar os contêineres." exit 1 fi # Define o diretório para armazenar as chaves SSL sslKeyDir="$caminho/mysql_keys" # Cria o diretório para armazenar as chaves SSL, se não existir if ! mkdir -p "$sslKeyDir"; then alertaVermelho "Erro ao criar o diretório $sslKeyDir" exit 1 fi # Modifica a propriedade do diretório para o usuário ihx e o grupo ihx if ! sudo chown ihx:ihx "$sslKeyDir"; then alertaVermelho "Erro ao mudar a propriedade do diretório $sslKeyDir para ihx:ihx" exit 1 fi # Gera uma senha randômica senhaChave=$(openssl rand -base64 48) echo "$senhaChave" > "$sslKeyDir/senha.txt" chmod 600 "$sslKeyDir/senha.txt" # Gera a chave e o certificado do servidor if ! openssl req -x509 -newkey rsa:2048 -keyout "$sslKeyDir/server-key-enc.pem" \ -out "$sslKeyDir/server-cert.pem" \ -subj "/C=BR/ST=MG/L=Juiz de Fora/O=IHX Sistema/OU=Tecnologia/CN=server/emailAddress=contato@ihxsistema.com.br" \ -passout pass:"$senhaChave"; then alertaVermelho "Erro ao gerar a chave e certificado do servidor." exit 1 else alertaVerde "Chave e o certificado do servidor gerados com sucesso!" fi # Decodifica a chave do servidor if ! openssl rsa -in "$sslKeyDir/server-key-enc.pem" -out "$sslKeyDir/server-key.pem" \ -passin pass:"$senhaChave" -passout pass:"$senhaChave"; then alertaVermelho "Erro ao decodificar chave servidor." exit 1 else alertaVerde "Chave do servidor decodificada com sucesso!" fi # Gera a chave e o certificado do cliente if ! openssl req -x509 -newkey rsa:2048 -keyout "$sslKeyDir/client-key-enc.pem" \ -out "$sslKeyDir/client-cert.pem" \ -subj "/C=BR/ST=MG/L=Juiz de Fora/O=IHX Sistema/OU=Tecnologia/CN=client/emailAddress=contato@ihxsistema.com.br" \ -passout pass:"$senhaChave"; then alertaVermelho "Erro ao gerar a chave e certificado do cliente." exit 1 else alertaVerde "Chave e o certificado do cliente gerados com sucesso!" fi # Decodifica a chave do cliente if ! openssl rsa -in "$sslKeyDir/client-key-enc.pem" -out "$sslKeyDir/client-key.pem" \ -passin pass:"$senhaChave" -passout pass:"$senhaChave"; then alertaVermelho "Erro ao decodificar chave cliente." exit 1 else alertaVerde "Chave do cliente decodificada com sucesso!" fi # Combina os certificados de cliente e servidor no arquivo de certificados CA if ! cat "$sslKeyDir/server-cert.pem" "$sslKeyDir/client-cert.pem" > "$sslKeyDir/ca-cert.pem"; then alertaVermelho "Erro ao combinar certificado do cliente e servidor no arquivo de certificados CA." exit 1 else alertaVerde "Certificado do cliente e servidor combinados no arquivo de certificados CA com sucesso!" fi # Verifica o Certificado do Servidor if ! openssl verify -CAfile "$sslKeyDir/ca-cert.pem" "$sslKeyDir/server-cert.pem"; then alertaVermelho "Erro ao verificar certificado do servidor." exit 1 else alertaVerde "Certificado do servidor verificado com sucesso!" fi # Verifica o Certificado do Cliente if ! openssl verify -CAfile "$sslKeyDir/ca-cert.pem" "$sslKeyDir/client-cert.pem"; then alertaVermelho "Erro ao verificar certificado do cliente." exit 1 else alertaVerde "Certificado do cliente verificado com sucesso!" fi # Substituição do arquivo custom_ssl.cnf pelo arquivo custom.cnf alertaAzul "Substituindo o arquivo custom_ssl.cnf pelo arquivo custom.cnf..." if ! cp -f "$caminho/Config/custom_ssl.cnf" "$caminho/Config/custom.cnf"; then alertaVermelho "Erro ao realizar a substituição do arquivo custom.cnf." exit 1 else alertaVerde "Substituição do arquivo custom.cnf realizada com sucesso!" fi # Remove as chaves codificadas para garantir a segurança alertaAzul "Removendo as chaves codificadas..." if ! rm -f "$sslKeyDir/client-key-enc.pem" "$sslKeyDir/server-key-enc.pem"; then alertaVermelho "Erro ao remover as chaves codificadas." exit 1 else alertaVerde "Chaves codificadas removidas com sucesso!" fi # Obtém a data atual no formato AAAA-MM-DD dataAtual=$(date +%F) # Nome do arquivo zip seguindo o padrão keys_data_cliente.zip nomeArquivoZip="keys_${dataAtual}_${cliente}.zip" # Compacta os arquivos especificados em um arquivo .zip alertaAzul "Compactando as chaves..." if zip -j "$sslKeyDir/$nomeArquivoZip" \ "$sslKeyDir/ca-cert.pem" \ "$sslKeyDir/client-cert.pem" \ "$sslKeyDir/client-key.pem"; then alertaVerde "Chaves compactadas com sucesso no arquivo $nomeArquivoZip." # Altera a propriedade do arquivo zip para o usuário ihx e o grupo ihx if sudo chown ihx:ihx "$sslKeyDir/$nomeArquivoZip"; then alertaVerde "Propriedade do arquivo $nomeArquivoZip alterada para ihx:ihx com sucesso." else alertaVermelho "Erro ao alterar a propriedade do arquivo $nomeArquivoZip." exit 1 fi else alertaVermelho "Erro ao compactar as chaves." exit 1 fi # Define os detalhes de login do Nextcloud nextcloudUser='talesam@gmail.com' nextcloudPass='nmYiiahisDA5653' # Substitua MINHA_SENHA pela sua senha real nextcloudURL="https://cloud.talesam.org/remote.php/dav/files/$nextcloudUser/" # O caminho completo da pasta no Nextcloud onde o arquivo será salvo # Os espaços e caracteres especiais são codificados para URL nextcloudDirPath="Servidor/Docker/Fran%C3%A7ois/IHX%20Access%20Pro/Keys" # Caminho local do arquivo que deseja enviar localFilePath="$sslKeyDir/$nomeArquivoZip" # Nome do arquivo no Nextcloud, incluindo o caminho da pasta onde deve ser salvo nextcloudFilePath="$nextcloudDirPath/$nomeArquivoZip" # Envia o arquivo para o Nextcloud e captura a resposta HTTP alertaAzul "Enviando o arquivo com as keys para o Nextcloud..." response=$(curl -w "%{http_code}" -u "$nextcloudUser:$nextcloudPass" -T "$localFilePath" "$nextcloudURL$nextcloudFilePath" -o /dev/null -s) # Verifica se o upload foi bem-sucedido analisando o código de resposta HTTP if [ "$response" -eq 201 ]; then alertaVerde "Arquivo enviado para o Nextcloud com sucesso!!" elif [ "$response" -eq 204 ]; then alertaVerde "Arquivo substituído com sucesso no Nextcloud." else alertaVermelho "Erro ao enviar arquivo para o Nextcloud: HTTP status $response." exit 1 fi # Iniciar os contêineres alertaAzul "Iniciando os contêineres com SSL ativo no banco de dados..." if ! cd "$caminho" || ! docker-compose up -d; then alertaVermelho "Erro ao iniciar contêineres." exit 1 else alertaVerde "Contêineres iniciados com sucesso!" fi # Chama a função pause pause " Tecle [Enter] para voltar ao menu..." && sleep 1 && clear } ### Função para remover uma aplicação removerAplicacao() { # Limpa a tela clear # Listar os Diretórios baseDir="$HOME/Docker/IHX_Access_Pro/" IFS=$'\n' read -d '' -r -a dirArray < <(ls -d "$baseDir"*/ && printf '\0') # Exibir o Menu alertaAzul "Escolha a aplicação que deseja remover:" for i in "${!dirArray[@]}"; do dirName=$(basename "${dirArray[$i]}") echo -e "${BLU}$((i + 1)))${STD} $dirName" done # Adicionada a opção de voltar echo -e "${ROS}$(( ${#dirArray[@]} + 1 )))${STD} Voltar ao menu principal" # Seleção do Usuário echo "" read -p "Escolha um número: " choice # Se o usuário escolher 'Voltar ao menu principal' if [ "$choice" -eq "$(( ${#dirArray[@]} + 1 ))" ]; then return fi cliente=$(basename "${dirArray[$((choice - 1))]}") # Define o caminho do diretório do cliente caminho="$HOME/Docker/IHX_Access_Pro/$cliente" # Entra no diretório do cliente if ! cd "$caminho"; then alertaVermelho "Erro ao entrar no diretório $caminho." exit 1 fi # Desativa a aplicação alertaAzul "Desativando a aplicação para ser removida..." if ! docker-compose down; then alertaVermelho "Erro ao desativar a aplicação com docker-compose down." exit 1 else alertaVerde "Aplicação desativada com sucesso." fi # Lê a porta que estava em uso a partir do arquivo .env if [ -f ".env" ]; then source .env porta=${porta_db:-} if [ -z "$porta" ]; then alertaVermelho "Porta não definida no arquivo .env." exit 1 fi else alertaVermelho "Arquivo .env não encontrado. Não é possível determinar a porta para bloquear no firewall." exit 1 fi # Retorna ao diretório anterior cd - > /dev/null 2>&1 || { alertaVermelho "Erro ao retornar ao diretório anterior."; return 1; } # Remove o diretório da aplicação if ! sudo rm -rf "$caminho"; then alertaVermelho "Erro ao remover o diretório $caminho." exit 1 else alertaVerde "Diretório $caminho removido com sucesso." fi # Bloqueia a porta no firewall if ! sudo ufw delete allow "$porta/tcp"; then alertaVermelho "Erro ao bloquear a porta $porta no firewall." exit 1 else alertaVerde "Porta $porta bloqueada no firewall com sucesso." fi alertaVerde "Aplicação removida e porta bloqueada com sucesso." # Chama a função pause pause " Tecle [Enter] para voltar ao menu..." } ### FIM FUNÇÕES ### # ------- MENU ------- # Mostra o menu while true; do clear echo -e " ${BLU}SCRIPT DE INSTALAÇÃO DO IHX ACCESS PRO -${STD} ${YEL}${Ver}${STD}" echo "" echo "" echo -e " ${BLU}1) Instalar aplicação IHX${STD}" echo -e " ${GRE}2) Instalar certificado${STD}" echo -e " ${RED}3) Remover aplicação IHX${STD}" echo -e " ${YEL}0) Sair${STD}" echo "" read -p " Escolha uma opção: " escolha case $escolha in 1) instalarIHX ;; 2) instalarCertificado ;; 3) removerAplicacao ;; 0) exit ;; *) alertaAmarelo "Opção inválida" ;; esac done