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.
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.
$ 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.
$ sudo docker image build --tag=mock-casino-image mock-casino
Obs: Favor reportar quaisquer problemas na geração da imagem.
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
Entre no seu browser, através do endereço https://127.0.0.1
.
Se estiver correto irá aparecer a tela a seguir.
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.
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.
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.
# 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
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
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.
$ 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
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
$ /usr/local/bin/chromedriver --whitelisted-ips * & # # whitelisted-ips - lista de IPs com conexões permitidas