$SSH_KEY_FILENAME = "id_rsa_arete" $global:UNIID = '' $ACCESS_TOKEN_FILE = 'access_token' $global:ACCESS_TOKEN = '' $SSH_TUNNEL_PORT = "5050" $HTTP_PROXY_PORT = "3128" function Request-Uniid { $global:UNIID = Read-Host "Please enter your uniid" } function Request-Access-Token { Write-Host "1. Gitlab access`n" if ( -not(Test-Path -Path .\$ACCESS_TOKEN_FILE -PathType Leaf) ) { Write-Host "Please create a personal access token on gitlab with (api, read_registry) scope(s)" Write-Host "https://gitlab.cs.ttu.ee/-/profile/personal_access_tokens?name=Arete+Setup+Token&scopes=api,read_registry" # -MaskInput does not work for some reason $global:ACCESS_TOKEN = Read-Host "Enter it here" -AsSecureString $global:ACCESS_TOKEN = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($global:ACCESS_TOKEN)) } else { Write-Host "Found access token file, using access token in: `"$ACCESS_TOKEN_FILE`"" -ForegroundColor Green $global:ACCESS_TOKEN = Get-Content .\$ACCESS_TOKEN_FILE -Raw } } function Save-Access-Token { if ( -not(Test-Path -Path .\$ACCESS_TOKEN_FILE -PathType Leaf) ) { $global:ACCESS_TOKEN | Out-File $ACCESS_TOKEN_FILE } } function Send-Key-To-Gitlab { Write-Host "Adding public key to gitlab account" $public_key = Get-Content .\$SSH_KEY_FILENAME.pub -Raw $postParams = @{private_token="$global:ACCESS_TOKEN";title='Arete SSH Key';key="$public_key"} Invoke-WebRequest -Uri https://gitlab.cs.ttu.ee/api/v4/user/keys -Method POST -Body $postParams | Out-Null } function Test-SSH-Connection($second_try) { cmd.exe /c "ssh git@gitlab.cs.ttu.ee -i .\id_rsa_arete -o PasswordAuthentication=no -o StrictHostKeyChecking=no >nul 2>&1" $status = $? if ( -not($status) ) { Write-Host "Failed to connect to gitlab" -ForegroundColor Red Send-Key-To-Gitlab if ( $second_try ) { Write-Host "Failed to add ssh key with personal access token, please check that you entered it correctly" -ForegroundColor Red exit } Test-SSH-Connection($true) } else { Write-Host "Successfully connected to gitlab`n" -ForegroundColor Green Save-Access-Token } } function Add-SSH-Key-To-Gitlab { Write-Host "`n2. Setting up ssh connection to gitlab`n`n" if ( -not(Test-Path -Path ./$SSH_KEY_FILENAME -PathType Leaf) ) { ssh-keygen -q -b 2058 -C arete-test -f $SSH_KEY_FILENAME -t rsa -N '""' Write-Host "Created rsa key $SSH_KEY_FILENAME`n`n" Send-Key-To-Gitlab Write-Host "Testing connection to gitlab`n`n" } else { Write-Host "Key file already exists, testing connection to gitlab`n`n" } Test-SSH-Connection Write-Host "Copying ssh key to arete" (mkdir -p "/arete/ssh" -ErrorAction "silentlycontinue") | Out-Null (Copy-Item "$SSH_KEY_FILENAME" "/arete/ssh") | Out-Null } function Restart-Docker { {Start-Process -Wait -NoNewWindow powershell "-Verb runAs --command `"restart-service *docker* >nul 2>&1 `"" -Passthru -RedirectStandardOutput ".\NUL" ; Test-Path ".\NUL"} | Out-Null Start-Sleep -s 10 } function Start-Docker-Desktop { Get-Process -Name "Docker Desktop" -Erroraction "silentlycontinue" | Out-Null $status = $? if ( -not($status) ) { & '..\Docker Desktop.lnk' Write-Host "Waiting 30 seconds for docker to properly start`n" Start-Sleep -s 30 } } function Install-Docker { if ( -not(Test-Path -Path ./docker-desktop.exe -PathType Leaf) ) { Start-BitsTransfer -Source "https://desktop-stage.docker.com/win/main/amd64/79160/Docker%20Desktop%20Installer.exe" -Destination "./docker-desktop.exe" } Start-Process './docker-desktop.exe' -ArgumentList 'install --quiet' -Wait $status=$? if ( -not($status) ) { Write-Host "Failed to install Docker Desktop" -ForegroundColor Red exit } Start-Docker-Desktop Write-Host "Successfully installed Docker Desktop" -ForegroundColor Green Write-Host "Docker Desktop requires that you log out and log back in for the install to finish" -ForegroundColor Red exit } function Install-Python { Start-BitsTransfer -Source "https://www.python.org/ftp/python/3.10.4/python-3.10.4-amd64.exe" -Destination "./python310.exe" Start-Process 'python310.exe' -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait $status=$? if ( -not($status) ) { Write-Host "Failed to install Python" -ForegroundColor Red exit } Write-Host "Successfully installed Python" -ForegroundColor Green } function Test-Requirements { Write-Host "2. Checking if requirements are present`n" Write-Host "Checking for WSL2" cmd.exe /c "wsl.exe --status >nul 2>&1" $status = $? if ( -not($status) ) { Write-Host "WSL2 is not installed`nPlease install WSL2 before continuing with `"wsl --install`"" -ForegroundColor Red exit } else { Write-Host "WSL2 is present" -ForegroundColor Green } Write-Host "`n`nChecking for docker" cmd.exe /c "docker -v >nul 2>&1" $status = $? if ( -not($status) ) { Write-Host "Docker is not installed`n" -ForegroundColor Red Write-Host "Attempting to automatically install docker, please wait for it to finish" Install-Docker } else { Write-Host "Docker is present" -ForegroundColor Green Write-Host "Checking that docker desktop is the right version" $out=Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName,DisplayVersion | Where-Object {$_.DisplayName -like "Docker*" -and $_.DisplayVersion -like "4.9.0"} if ( $null -eq $out ) { Write-Host "Docker desktop version too old, updating..." -ForegroundColor Red Install-Docker } else { Start-Docker-Desktop } } Write-Host "`n`nChecking for python" cmd.exe /c "python.exe --version >nul 2>&1 || py.exe --version >nul 2>&1" $status = $? if ( -not($status) ) { Write-Host "Python is not installed`n" -ForegroundColor Red Write-Host "Attempting to automatically install python, please wait for it to finish" Install-Python } else { Write-Host "Python is present" -ForegroundColor Green } Write-Host "`n" Install-pproxy } function Install-pproxy { Write-Host "Checking for python module pproxy" $python_executable = cmd.exe /c "where python.exe 2>nul || where py.exe 2>nul" cmd.exe /c "`"$python_executable`" -m pproxy --version >nul 2>&1" $status = $? if ( -not($status) ) { Write-Host "Installing pproxy" cmd.exe /c "`"$python_executable`" -m pip install pproxy >nul" $status = $? if ( -not($status) ) { Write-Host "Failed to install python module pproxy" -ForegroundColor Red } } Write-Host "Module pproxy is present`n" -ForegroundColor Green } function Process-Exists-And-Running($program) { if ( -not(Test-Path -Path .\$program.pid -PathType Leaf) ) { return $false } else { $process_id = Get-Content .\$program.pid -Raw Get-Process -Id $process_id -Erroraction "silentlycontinue" | Out-Null return $? } } function Start-Process-Background($program, $arguments) { $process_running = Process-Exists-And-Running $program if ( -not($process_running) ) { $process = Start-Process -NoNewWindow $program "$arguments" -Passthru -RedirectStandardOutput ".\NUL" ; Test-Path ".\NUL" | Out-Null $process.Id | Out-File .\$program.pid } } function Stop-Process-Background($program) { $pidfile = "$program.pid" if ( Test-Path -Path $pidfile -PathType Leaf -ErrorAction "silentlycontinue" ) { $process_id = Get-Content $pidfile -Raw Get-Process -Id $process_id -Erroraction "silentlycontinue" | Out-Null $status = $? if ( $status ) { Stop-Process -Id $process_id } Remove-Item -Force -ErrorAction "silentlycontinue" $pidfile } } function Start-SSH-Tunnel { Write-Host "Starting ssh tunnel" return Start-Process-Background "ssh" "-o StrictHostKeyChecking=no -o ExitOnForwardFailure=yes -f -N -D :$SSH_TUNNEL_PORT $global:UNIID@enos.itcollege.ee -i .\$SSH_KEY_FILENAME" } function Stop-SSH-Tunnel { Write-Host "Stopping ssh tunnel" Stop-Process-Background "ssh" } function Setup-SSH-Tunnel { Write-Host "3. Setting up ssh tunnel connection to enos.itcollege.ee on port :$SSH_TUNNEL_PORT`n" Write-Host "If you have not set up ssh connection before to enos.itcollege.ee, it will ask for your uni-ID password" cmd.exe /c "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -l $global:UNIID enos.itcollege.ee -i .\id_rsa_arete whoami >nul 2>&1" $status = $? if ( -not($status) ) { cmd.exe /c "type .\id_rsa_arete.pub | ssh -o StrictHostKeyChecking=no -i .\$SSH_KEY_FILENAME $global:UNIID@enos.itcollege.ee `"umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys`"" } Start-SSH-Tunnel Write-Host "" } function Start-pproxy { Write-Host "Starting pproxy" $python_executable = cmd.exe /c "where python.exe 2>nul || where py.exe 2>nul" $python_executable = ((Get-Item $python_executable).name -split '\n')[0] Start-Process-Background $python_executable "-m pproxy -l http+socks4+socks5://:$HTTP_PROXY_PORT/ -r socks5://localhost:$SSH_TUNNEL_PORT -v" } function Stop-pproxy { Write-Host "Stopping pproxy" $python_executable = cmd.exe /c "where python.exe 2>nul || where py.exe 2>nul" $python_executable = ((Get-Item $python_executable).name -split '\n')[0] Stop-Process-Background $python_executable } function Setup-pproxy { Write-Host "4. Setting up pproxy on port :$HTTP_PROXY_PORT" Start-pproxy Write-Host "" } function Set-Docker-Proxy { Write-Host "5. Configuring docker to use proxy`n" $original_data_config = Get-Content $HOME\.docker\config.json | ConvertFrom-Json $original_data_config | Add-Member -Name "proxies" -Value @{default=@{httpProxy="http://localhost:$HTTP_PROXY_PORT";httpsProxy="http://localhost:$HTTP_PROXY_PORT"}} -MemberType NoteProperty -Force $original_data_config | ConvertTo-Json | Out-File -Encoding Ascii $HOME\.docker\config.json $original_data_http_proxy = Get-Content $HOME\AppData\Roaming\Docker\http_proxy.json | ConvertFrom-Json $original_data_http_proxy | Add-Member -Name "http" -Value "http://localhost:$HTTP_PROXY_PORT" -MemberType NoteProperty -Force $original_data_http_proxy | Add-Member -Name "https" -Value "http://localhost:$HTTP_PROXY_PORT" -MemberType NoteProperty -Force $original_data_http_proxy | ConvertTo-Json | Out-File -Encoding Ascii $HOME\AppData\Roaming\Docker\http_proxy.json Write-Host "Configured Docker proxies, restarting docker...`n`n" -ForegroundColor Green Restart-Docker } function Set-Docker-Login { Write-Host "7. Logging docker into gitlab regisrtry" cmd.exe /c "docker login gitlab.cs.ttu.ee:5050 -u $global:UNIID -p $global:ACCESS_TOKEN >nul" $status = $? if ( -not($status) ) { Write-Host "Failed to login to gitlab registry" -ForegroundColor Red exit } Write-Host "Successfully logged into gitlab registry`n" -ForegroundColor Green } function Test-Image-Access { Write-Host "8. Pulling required images:" Write-Host "`t* https://gitlab.cs.ttu.ee/testing/automated-testing-service" Write-Host "`t* https://gitlab.cs.ttu.ee/testing/authentication-service" Write-Host "`t* https://gitlab.cs.ttu.ee/testing/monitoring-service`n" $required_images = @("automated-testing-service:latest", "authentication-service:latest", "monitoring-service:latest") foreach ($image in $required_images) { cmd.exe /c "docker pull gitlab.cs.ttu.ee:5050/testing/$image" $status = $? if ( -not($status) ) { Write-Host "Failed to pull image $image" -ForegroundColor Red Write-Host "At minimum you need reporter level access to the image's repository to pull the image." exit } Write-Host "Image ${image} has been pulled`n" -ForegroundColor Green } } function Create-Env-File { if ( -not(Test-Path -Path .\.env -PathType Leaf) ) { Write-Host "Creating .env file" Add-Content -Path .\.env -Value "GITLAB_REGISTRY_USER=$global:UNIID" Add-Content -Path .\.env -Value "GITLAB_REGISTRY_TOKEN=$global:ACCESS_TOKEN" Write-Host "" } } function Uninstall-arete { Write-Host "Uninstalling arete" cmd.exe /c "docker-compose -f docker-compose-arete.yaml down" } function Uninstall-files { Write-Host "Removing downloaded and created files and folders" Remove-Item -r -Force .env, docker-compose-arete.yaml, id_rsa_arete*, nginx.conf, access_token, /arete, docker-desktop.exe, python310.exe -ErrorAction "silentlycontinue" } function Start-Arete { return cmd.exe /c "docker-compose -f docker-compose-arete.yaml up -d --force-recreate" } function Stop-Arete { return cmd.exe /c "docker-compose -f docker-compose-arete.yaml stop" } function Build-Arete { Write-Host "5. Building arete" if ( -not(Test-Path -Path .\docker-compose-arete.yaml -PathType Leaf) ) { Write-Host "Downloading docker-compose-arete.yaml" $url = "https://ained.pages.taltech.ee/it-doc/_static/docker-compose-arete.yaml" Start-BitsTransfer -Source "$url" -Destination "./docker-compose-arete.yaml" $status = $? if ( -not($status) ) { Write-Host "Failed to download docker-compose-arete.yaml at $url" -ForegroundColor Red exit } } if ( -not(Test-Path -Path .\nginx.conf -PathType Leaf) ) { Write-Host "Downloading nginx.conf" $url = "https://ained.pages.taltech.ee/it-doc/_static/nginx.conf" Start-BitsTransfer -Source "$url" -Destination "./nginx.conf" $status = $? if ( -not($status) ) { Write-Host "Failed to download nginx.conf at $url" -ForegroundColor Red exit } } Start-Arete $status = $? if ( $status ) { Write-Host "All the services should now be available:" Write-Host "Monitoring Service: http://localhost:8080/services/arete/" Write-Host "Authentication Service: http://localhost:8001/" Write-Host "Automated Testing Service: http://localhost:8098/" } } function help { Write-Host "Arete setup helper script." Write-Host "Commands:" Write-Host "* install" Write-Host " Installs the complete arete system" Write-Host " 1. Generates an id_rsa key then sends the public key to gitlab to set up access to gitlab for arete" Write-Host " 2. Installs all the requirements (docker, docker-compose, sshuttle), then starts docker, ssh tunnel and pproxy" Write-Host " 3. Logs docker into the gitlab registry" Write-Host " 4. Creates .env file containing the required info" Write-Host " 5. Downloads the docker-compose file and nginx conf, then builds arete" Write-Host "* uninstall" Write-Host " Uninstalls the arete systems and cleans up requirements" Write-Host " 1. Stops arete and removes arete containers" Write-Host " 2. Removes downloaded and created files and folder associated with arete" Write-Host "* start" Write-Host " Skips installing requirements and only starts the needed services" Write-Host " 1. Starts docker" Write-Host " 2. Starts SSH tunnel" Write-Host " 3. Starts pproxy" Write-Host " 4. Starts arete" Write-Host "* start-proxy" Write-Host " Only starts the tunnel which redirects traffic through enos.itcollege.ee" Write-Host " 1. Starts SSH tunnel" Write-Host " 2. Starts pproxy" Write-Host "* stop-proxy" Write-Host " Only stops the tunnel which redirects traffic through enos.itcollege.ee" Write-Host " 1. Stops the SSH tunnel" Write-Host " 2. Stops pproxy" Write-Host "* stop" Write-Host " Stops all arete services and services required by arete (except docker)" Write-Host " 1. Stops the SSH tunnel" Write-Host " 2. Stops pproxy" Write-Host " 3. Stops arete" } function Process-Args($arg) { if ( ($arg -eq "-h") -or ($arg -eq "help") -or ($arg -eq "h") -or ($arg -eq "--help")) { help } elseif (($arg -eq "install")) { Request-Uniid Request-Access-Token Add-SSH-Key-To-Gitlab Test-Requirements Setup-SSH-Tunnel Setup-pproxy Set-Docker-Proxy Set-Docker-Login Test-Image-Access Create-Env-File Build-Arete } elseif (($arg -eq "start")) { Request-Uniid Start-SSH-Tunnel Start-pproxy Start-Arete } elseif (($arg -eq "start-proxy")) { Request-Uniid Start-SSH-Tunnel Start-pproxy } elseif (($arg -eq "stop-proxy")) { Stop-SSH-Tunnel Stop-pproxy } elseif (($arg -eq "stop")) { Stop-SSH-Tunnel Stop-pproxy Stop-arete } elseif (($arg -eq "uninstall")) { Stop-SSH-Tunnel Stop-pproxy Stop-arete Uninstall-arete Uninstall-files } else { help } } Process-Args $args[0] exit