Tabela de conteúdos
Tutorial para simular localmente o SSO CASino utilizando Docker
Este tutorial tem por objetivo criar um servidor local que responda de forma semelhante ao servidores CAS disponíveis em ambiente externo, mas possa ser configurado localmente.
Será abordada a construção da imagem na plataforma docker, sua execução e a configuração dos logins no SSO.
É necessário ter algum conhecimento prévio sobre docker e ciência de quais campos que virão das contas do SSO.
1. Construção da imagem docker
Os arquivos para a construção da imagem estão disponíveis no git.
Criaremos a imagem no docker e levantaremos o container com a imagem.
1.1. Baixar os arquivos disponíveis
$ git clone https://git.ufrj.br/josueresende/mock-casino.git
Descrição dos Arquivos | |
---|---|
\Dockerfile | Receita para a geração da imagem com Ruby 2.3 Foi utilizado como base em um projeto1) no site hub do docker. |
\Gemfile | Descreve as dependências para o programa em Ruby |
\cas.yml | Configuração de autenticadores e logins do programa |
\database.yml | Utilizado durante a instalação |
\certificate_authority-password_1234-privateKey.key | Chave privada da 'Certificate Authority' - senha: 1234 |
\certificate_authority-help.txt | Informações sobre a criação da 'Certificate Authority' e ajuda para os testes em Java |
\certificate_authority-rootCertificate.pem | Certificado da 'Certificate Authority' |
\certificate_authority-rootCertificate.srl | Arquivo com o serial criado (-CAcreateserial ) |
\casino.key | Private Key - Chave privada para o serviço |
\casino.csr | Certificate Signing Request |
\casino.ext | Extra - Dados para geração do certificado do serviço pela autoridade certificadora |
\docker-entrypoint.sh | Shell Script para gerar o certificado do serviço durante inicialização do container, alterando a linha IP.1 de acordo com o IP da máquina |
Há como substituir os arquivos ou diretórios através da montagem de volumes quando for levantar o container mais à frente.
O certificado SSL será gerado durante a inicialização do container.
1.2. Construindo a imagem no docker
$ sudo docker image build --tag=mock-casino-image mock-casino
Obs: Favor reportar quaisquer problemas na geração da imagem.
1.3. Levantando o container utilizando a imagem criada
Ao levantar o container, é possível vincular os arquivos internos a arquivos externos informando como volume.
Podemos vincular um arquivo de configuração ‘cas.yml’ externo para aquele que se encontra dentro do container em /var/www/app/casino_app/config/cas.yml.
Para configurar esse arquivo externo, veja a seção Configurando logins no CASino.
Abaixo, assumirei que o arquivo externo existe em: /mnt/fs_docker/mocks/cas.yml.
Através da linha de comando do docker2) levantamos o container. Obs: Abaixo temos apenas uma linha de comando.
$ sudo docker container run --name=mock-casino-container --detach --volume=/mnt/fs_docker/mocks/cas.yml:/var/www/app/casino_app/config/cas.yml --publish=443:443 mock-casino-image
1.4. Testando o CAS
Entre no seu browser, através do endereço https://127.0.0.1
.
Se estiver correto irá aparecer a tela a seguir.
2. Configurando logins no CASino
O arquivo de configuração do SSO CASino3), cas.yml, está em YAML4) que é o formato utilizado como padrão de serialização em Ruby.
Para termos o arquivo modificado, altere ou copie o cas.yml baixado .
Nesse arquivo, iremos alterar a coleção ‘users’ onde a chave é o login e abaixo ficam os campos de cada usuário. As partes exibidas abaixo são apenas um trecho do arquivo completo.
development: <<: *defaults authenticators: static: class: "CASino::StaticAuthenticator" options: users: "login-do-usuario": nome: "nome-do-usuario" password: "senha-do-usuario" email: "email-do-usuario" outro-campo: "bla bla bla ..." "login-do-usuario-2": nome: "nome-do-usuario-2" password: "senha-do-usuario-2" email: "email-do-usuario-2" outro-campo: "bla bla bla ..."
Modifique os campos do usuário na lista 'users' com os campos esperados respeitando a indentação.
O único campo obrigatório é o password, que serve para autenticar e não retorna na resposta.
users: "12345678909": nome: "JOAQUIM SILVA XAVIER" password: "123" email: "joaquimxavier@dominio.br" IdentificacaoUFRJ: "12345678909" matricula_siape: "123" registro_sira: "123" grupos: "tecnico_admin:aluno_pos" eh_tec_admin: "1" eh_aluno_grad: "---..." eh_aluno_pos: "0" eh_professor: "---..." ativo: "1"
É necessário reiniciar o SSO CASino para que as mudanças tenham efeito.
Obs: Para quem usa o CAS para autenticação e pega o perfil de usuário que vem de lá, a melhor maneira é pegar pelo atributo “grupos”, e ali terá uma string com todos os perfis que o usuário já teve na UFRJ. Os atributos “eh_<perfil>” só indicam se está em atividade no perfil.
3. Testes no ambiente com Laravel Dusk
Após as instalações do Dusk5) e execução do Chromedriver podemos realizar testes no ambiente.
Nosso .env.dusk terá pelo menos as seguintes linhas
# utilizo essa variável no script CHROMEDRIVER=http://172.18.0.1:9515 ROOT_USERNAME=12345678912 ROOT_PASSWORD=123 # abaixo seguem as utilizadas no projeto (.env) APP_ENV=dusk APP_DEBUG=true APP_URL=http://172.18.0.10/ CAS_HOST=172.18.0.30 CAS_CONTEXT="" CAS_PROXY=true
Para esta classe de teste,vamos sobrescrever criar os métodos driver/prepare/setUp na classe DuskTestCase, e incluir mais um método que insere o texto no input e confere seu valor.
... use Facebook\WebDriver\WebDriverBy; use Facebook\WebDriver\Chrome\ChromeOptions; use Facebook\WebDriver\Remote\DesiredCapabilities; use Facebook\WebDriver\Remote\RemoteWebDriver; . . . protected function driver() { $options = new ChromeOptions(); $options->addArguments([ '--disable-gpu', '--window-size=1920,1080', '--verbose', '--lang=pt-BR', // idioma do browser // '--headless', // <- browser sem tela ]); $options->setExperimentalOption( 'prefs', ['intl.accept_languages' => 'pt-BR'] ); return RemoteWebDriver::create( env('CHROMEDRIVER', NULL), DesiredCapabilities::chrome()->setCapability(ChromeOptions::CAPABILITY, $options) ); } public static function prepare() { static::startChromeDriver(); } protected function setUp() { $this->browse( function (Browser $browser) { $browser->visit(env('APP_URL', '')); # Fig: 1 // $browser->resize( 640, 480); sleep(5); // redimensionamentos de tela // $browser->resize( 800, 600); sleep(5); // $browser->resize(1024, 768); sleep(5); $browser->maximize(); sleep(1); // { // parte da rotina para fechar a DEBUGBAR $buttonDebugBares = $browser->driver->findElements( WebDriverBy::className('phpdebugbar-close-btn') ); foreach ($buttonDebugBares as $buttonDebugBar) { if ($buttonDebugBar->isDisplayed()) $buttonDebugBar->click(); } if (count($buttonDebugBares) > 0) sleep(2); } }); return parent::setUp(); // TODO: Change the autogenerated stub } ... // rotina que confere a digitação do texto em input protected function entrarDadosCorretamente($id, $value) { $this->browse( function (Browser $browser) use($id, $value) { do { $browser->type($id, $value); sleep(1); if ($browser->inputValue($id) == $value) break; } while(true); }); } ...
/** * @group T00 * @group US01-0 * @throws \Throwable */ public function test_Login_no_CAS() { $username = env('ROOT_USERNAME'); $password = env('ROOT_PASSWORD'); $this->browse( function (Browser $browser) use($username, $password) { $browser->assertSee('Acesso administrativo'); $browser->clickLink('Acesso administrativo'); # Fig: 2 self::entrarDadosCorretamente('username', $username); self::entrarDadosCorretamente('password', $password); $browser->click('button[type=submit]'); # Fig: 3 $browser->assertDontSee('Acesso administrativo'); }); }
Passos na figuras a seguir, em ordem:
As telas acima são do projeto Novo Conhecendo a UFRJ.
Anexo: Portainer – Docker Compose file format v2
Para execução do container no portainer editamos a stack que utilizará o mock.
Abaixo como exemplo na sua seção services6), segue:
casino: container_name: mock-casino-container hostname: casino image: mock-casino-image restart: unless-stopped mem_limit: 1G expose: - 443 networks: default: ipv4_address: 172.18.0.30 volumes: - /mnt/fs_docker/mocks/cas.yml:/var/www/app/casino_app/config/cas.yml
Obs: Nesse exemplo existem configurações que necessitam estar disponíveis anteriormente, como a rede.
Anexo: Exemplos de comando em Docker
# Listar todos os containers em execução $ sudo docker container ps
# Parar a execução do container $ sudo docker container stop mock-casino-container
# Remover um container $ sudo docker container rm mock-casino-container
# Executa o container e define que sempre será reiniciado, a menos que que seja parado $ sudo docker container run --restart=unless-stopped mock-casino-container
Anexo: Laravel Dusk (Básico)
1. Instalando
Dentro do projeto Laravel você deve incluir o componente do Laravel Dusk7)
# diretórios antes
tests
├── CreatesApplication.php
├── Feature
│ └── ExampleTest.php
├── TestCase.php
└── Unit
└── ExampleTest.php
$ composer require --dev laravel/dusk $ php artisan dusk:install
# diretórios depois
tests
├── Browser
│ ├── Components
│ ├── console
│ ├── ExampleTest.php
│ ├── Pages
│ │ ├── HomePage.php
│ │ └── Page.php
│ └── screenshots
├── CreatesApplication.php
├── DuskTestCase.php
├── Feature
│ └── ExampleTest.php
├── TestCase.php
└── Unit
└── ExampleTest.php
2. Configurando
Você precisa criar um arquivo de configuração de ambiente para o dusk na raiz do projeto como .env.dusk que pode ser igual .env dependendo do for precisar somente com o Laravel Dusk.
3. Criando testes
$ php artisan dusk:make T00_Test
# Cria uma classe de teste com o nome solicitado dentro do diretório # “tests/Browser” que estende “tests/DuskTestCase.php” tests/ ├── Browser │ ├── Components │ ├── console │ ├── ExampleTest.php │ ├── Pages │ │ ├── HomePage.php │ │ └── Page.php │ ├── screenshots │ └── T00_Test.php ├── CreatesApplication.php ├── DuskTestCase.php ├── Feature │ └── ExampleTest.php ├── TestCase.php └── Unit └── ExampleTest.php
4. Executando
Necessário ter o Chromedriver executando.
# O comando abaixo executa os testes seguindo a ordem alfabética de todos os testes
$ php artisan dusk
É possível executar por grupo de testes adicionando o parâmetro “–group”, que trabalha associado a anotação @group encontrada no comentário de um função ‘test’
$ php artisan dusk --group=T00
Anexo: Chromedriver
Instalando
- Baixar a aplicação em http://chromedriver.chromium.org/downloads (Obs: Preferência pela versão 2.*)
- Extrair o arquivo ZIP
- Disponibilizar o binário extraído como executável no PATH do ambiente (Ex: /usr/local/bin)
Executando
$ /usr/local/bin/chromedriver --whitelisted-ips * & # # whitelisted-ips - lista de IPs com conexões permitidas