converge/pkg/server/ui/usage.templ

271 lines
11 KiB
Plaintext

package ui
import "git.wamblee.org/converge/pkg/models"
templ AgentUsage(access models.ConvergeAccess, usageInputs UsageInputs) {
<div>
for _, message := range usageInputs.ErrorMessages {
<div class="alert alert-danger" role="alert">
{message}
</div>
}
<h2>downloading and running the agent</h2>
<p>
This is what you run on a remote server, typically in your continuous integration job.
</p>
if usageInputs.RemoteShells[BASH] {
<code-sample id="run-agent-bash">@templ.Raw(addSshKeys(BASH, usageInputs.SshKeys)) <br/>
{DOWNLOAD_COMMAND[usageInputs.DownloadCommand]} agent {GetDownloadSecureOption(usageInputs)} http{access.Secure}://{access.BaseUrl}/downloads/agent<br/>
chmod 755 agent <br/>
./agent {GetAgentSecureOption(usageInputs)} --id {usageInputs.Id} ws{access.Secure}://{access.BaseUrl}<br/>
rm -f agent <br/>
</code-sample>
}
if usageInputs.RemoteShells[CMD] {
<code-sample id="run-agent-cmd">@templ.Raw(addSshKeys(CMD, usageInputs.SshKeys)) <br/>
{DOWNLOAD_COMMAND[usageInputs.DownloadCommand]} agent.exe {GetDownloadSecureOption(usageInputs)} http{access.Secure}://{access.BaseUrl}/downloads/agent.exe <br/>
.\agent {GetAgentSecureOption(usageInputs)} --id {usageInputs.Id} ws{access.Secure}://{access.BaseUrl} <br/>
del agent.exe <br/>
</code-sample>
}
if usageInputs.RemoteShells[POWERSHELL] {
<code-sample id="run-agent-powershell">@templ.Raw(addSshKeys(POWERSHELL, usageInputs.SshKeys)) <br/>
{DOWNLOAD_COMMAND[usageInputs.DownloadCommand]} agent.exe {GetDownloadSecureOption(usageInputs)} http{access.Secure}://{access.BaseUrl}/downloads/agent.exe <br/>
.\agent {GetAgentSecureOption(usageInputs)} --id {usageInputs.Id} ws{access.Secure}://{access.BaseUrl} <br/>
del agent.exe <br/>
</code-sample>
}
<p>
The agent has more command-line options than shown here.
Download the agent and run it without arguments to
see all options.
</p>
<p>
<b>Tip</b>: Run the above command locally in a similar shell (for instance in a
docker container) then try to connect to the shell using the commands below. If that
works, then you are all set.
</p>
<h2>connecting to the agent</h2>
<p>
You need to install <code>wsproxy</code>, which is available in the <a href="downloads.html">downloads</a> section and
make it availebla in your path. This utility needs to be downloaded only once, if a newer version of
<code>wsproxy</code> is needed it will tell you about that.
</p>
<p>The embedded ssh server in the agent supports both ssh and sftp.
</p>
<code-sample id="ssh-connect">
ssh -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}" {"localhost"}
</code-sample>
<code-sample id="sftp-connect">
sftp -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}" {"localhost"}
</code-sample>
<p>For other ssh clients that do not support the openssh ProxyCommand option, there is another
way to connect. In this method, a local port forwarder is started that forwards a local port
to the webserver. Then you can start an ssh client that connects to the local tcp port.
</p>
<code-sample id="tcptows-ssh">ssh -oServerAliveInterval=10 -p 10000 {"localhost"}</code-sample>
<code-sample id="tcptows-sftp">sftp -oServerAliveInterval=10 -p 10000 {"localhost"}</code-sample>
<p>This requires the <code>tcptows</code> utility which is available in the
<a href="downloads.html">downloads</a> section. The utility must be started beforehand
using:
</p>
<code-sample id="tcptows-ssh">tcptows 10000 ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}</code-sample>
<h2>working with the agent</h2>
if usageInputs.RemoteShells[BASH] {
<div>
<code-sample id="session-bash">
# cd back to the agent directory <br/>
cd $agentdir <br/>
</code-sample>
<code-sample id="session-bash2">
# prevent logout when last user exits <br/>
touch $agentdir/.hold<br/>
</code-sample>
</div>
}
if usageInputs.RemoteShells[CMD] {
<div>
<code-sample id="session-cmd">
# cd back to the agent directory <br/>
cd %agentdir% <br/>
</code-sample>
<code-sample id="session-cmd2">
# prevent logout when last user exits <br/>
echo > %agentdir%\.hold <br/>
</code-sample>
</div>
}
if usageInputs.RemoteShells[POWERSHELL] {
<div>
<code-sample id="session-powershell">
# cd back to the agent directory <br/>
cd $env:agentdir <br/>
</code-sample>
<code-sample id="session-powershell2">
# prevent logout when last user exits <br/>
$null > $env:agentdir\.hold <br/>
</code-sample>
</div>
}
if usageInputs.RemoteShells[CMD] || usageInputs.RemoteShells[POWERSHELL] {
<p>
NOTE: When running the agent on windows, an exit of the remote session using
exit in powershell or command prompt does not terminate the shell completely.
To terminate the client ssh session must be killed by closing the terminal.
Cleanup of remote processes on the agent appears to work properly despite this
problem. It is just that exit of the windows shell (powershell or command prompt)
is not detected properly.
</p>
}
</div>
}
templ ShellUsage(access models.ConvergeAccess, usageInputs UsageInputs) {
<div>
@AgentUsage(access, usageInputs)
</div>
}
templ Usage(access models.ConvergeAccess) {
<div>
<h1>usage</h1>
<p>
<ol>
<li>Configure agent settings below</li>
<li>Copy paste the required commands for your agent</li>
<li>Copy paste the required commands for connecting to the remote shell on the agent through
Converge. </li>
</ol>
</p>
<!-- TODO Investigate how to do this properly with bootstrap -->
<style>
.minimal-width {
width: 1%;
white-space: nowrap;
}
</style>
<form id="inputs" novalidate
class="persistent-form"
hx-post="../usage"
method="post"
hx-trigger="load,input delay:500ms,change,formdataloaded"
hx-target="#example-cli"
hx-on::after-request="saveFormToCookieEvent(event)">
<table class="table table-responsive">
<tr>
<td class="minimal-width">
<label
for="rendez-vous-id"
data-toggle="tooltip"
title="this allows the remote agent and client to find each other">
rendez-vous id<sup><i class="bi bi-info-circle small"></i></sup>
</label>
</td>
<td>
<input id="rendez-vous-id" class="form-control" name="rendez-vous-id" type="text" maxlength="40"></input>
</td>
</tr>
<tr>
<td class="minimal-width">
<label
for="ssh-keys"
data-toggle="tooltip"
title="public SSH public keys define which users are allowed to connect">
public ssh keys<sup><i class="bi bi-info-circle small"></i></sup>
</label>
</td>
<td>
<textarea id="ssh-keys" class="form-control autogrow" name="ssh-keys" rows="5"></textarea>
</td>
</tr>
<tr>
<td class="minimal-width"><label
for="remote-shell"
data-toggle="tooltip"
title="is the agent running on linux (sh-like shell) or windows?">
agent environment<sup><i class="bi bi-info-circle small"></i></sup></label>
</td>
<td>
<input checked id="remote-shell-0" name="remote-shell" type="radio" value={string(BASH)}> <label for="remote-shell-0">bash, sh, zsh, ...</label>
<input id="remote-shell-1" name="remote-shell" type="radio" value={string(CMD)}> <label for="remote-shell-1">command prompt</label>
<input id="remote-shell-2" name="remote-shell" type="radio" value={string(POWERSHELL)}> <label for="remote-shell-2">power shell</label>
</td>
</tr>
<tr>
<td class="minimal-width">
<label
for="download-command"
data-toggle="tooltip"
title="how is the agent downloaded to the remote environment?">
download method<sup><i class="bi bi-info-circle small"></i></sup>
</label>
</td>
<td>
<input checked id="download-command-0" name="download-command" type="radio" value={string(CURL)}> <label for="download-command-0">curl</label>
<input id="download-command-1" name="download-command" type="radio" value={string(WGET)}> <label for="download-command-1">wget</label>
</td>
</tr>
<tr>
<td class="minimal-width">
<label
for="certificate-validation"
data-toggle="tooltip"
title="turn off certificate validation if the converge certificate is untrusted by the remote system">
certificate validation<sup><i class="bi bi-info-circle small"></i></sup>
</label>
</td>
<td>
<input checked id="certificate-validation-0" name="certificate-validation" type="checkbox" checked> <label for="certificate-validation-0"></label>
</td>
</tr>
<!--tr>
<td class="minimal-width"><label for="local-shell">local environment</label></td>
<td>
<input id="checked local-shell-0" name="local-shell" type="radio" value={BASH}> <label for="local-shell-0">*sh</label>
<input id="local-shell-1" name="local-shell" type="radio" value={CMD}> <label for="local-shell-1">command prompt</label>
<input id="local-shell-2" name="local-shell" type="radio" value={POWERSHELL}> <label for="local-shell-2">powershell</label>
</td>
</tr -->
</table>
</form>
<div id="example-cli">
</div>
</div>
}
templ UsageTab(access models.ConvergeAccess) {
@BasePage(2) {
@Usage(access)
}
}
templ ShellUsageTab(access models.ConvergeAccess, usageInputs UsageInputs) {
@BasePage(2) {
@ShellUsage(access, usageInputs)
}
}