* usage page now has more dynamic part where user can enter id and publis ssh keys and the server will generate the appropriate commmands to execute depending on the local and remote shell.
313 lines
13 KiB
Plaintext
313 lines
13 KiB
Plaintext
package templates
|
|
|
|
import "converge/pkg/models"
|
|
|
|
templ Usage(access models.ConvergeAccess) {
|
|
<div>
|
|
|
|
|
|
<h1>Usage</h1>
|
|
|
|
<style>
|
|
.minimal-width {
|
|
width: 1%;
|
|
white-space: nowrap;
|
|
}
|
|
</style>
|
|
|
|
<form id="inputs" novalidate
|
|
hx-post="/usage"
|
|
method="post"
|
|
hx-trigger="load,input delay:500ms,change"
|
|
hx-target="#example-cli"
|
|
hx-on::after-request="saveFormToCookie()">
|
|
<table class="table table-responsive">
|
|
<tr>
|
|
<td class="minimal-width"><label for="rendez-vous-id">rendez-vous id</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">public ssh keys</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">remote shells</label></td>
|
|
<td>
|
|
<input checked id="remote-shell-0" name="remote-shell" type="checkbox" value="*sh"> <label for="remote-shell-0">*.sh</label>
|
|
<input id="remote-shell-1" name="remote-shell" type="checkbox" value="cmd"> <label for="remote-shell-1">cmd.exe</label>
|
|
<input id="remote-shell-2" name="remote-shell" type="checkbox" value="cmd"> <label for="remote-shell-2">powerpoint.exe</label>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="minimal-width"><label for="local-shell">local shell</label></td>
|
|
<td>
|
|
<input id="checked local-shell-0" name="local-shell" type="checkbox" value="*sh"> <label for="local-shell-0">*.sh</label>
|
|
<input id="local-shell-1" name="local-shell" type="checkbox" value="cmd"> <label for="local-shell-1">cmd.exe</label>
|
|
<input id="local-shell-2" name="local-shell" type="checkbox" value="cmd"> <label for="local-shell-2">powerpoint.exe</label>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</form>
|
|
|
|
<div id="example-cli">
|
|
</div>
|
|
|
|
<h1>usage old</h1>
|
|
|
|
<h2>Continuous integration jobs</h2>
|
|
|
|
<p>
|
|
In a
|
|
continuous integration job, download the agent, chmod it and run it.
|
|
</p>
|
|
<pre>{`
|
|
# linux
|
|
`}curl http{access.Secure}://{access.HostPort}/static/agent > agent{`
|
|
chmod 755 agent
|
|
`}./agent --id ID ws{access.Secure}://{access.HostPort}{`
|
|
rm -f agent
|
|
|
|
# windows
|
|
`}curl http{access.Secure}://{access.HostPort}/static/agent.exe > agent.exe{`
|
|
`}agent --id ID ws{access.Secure}://{access.HostPort}{`
|
|
del agent.exe
|
|
`}</pre>
|
|
<p>
|
|
Above, ID is a unique id for the job, the so-called rendez-cous ID. This should not conflict with IDs
|
|
used by other agents. The ID is used for a rendez-vous between the end-user on a local system and
|
|
the continuous integration job running on a build agent. If you don't specify an id, a random
|
|
id will be generated. If you specify a duplicate ID, the server will generate a new one andd the
|
|
agent will tell you what id to use.
|
|
Clients can now connect to the Converge server with the ID to establish a connection to
|
|
the CI job through Converge.
|
|
|
|
Communication between
|
|
end-user and agent is encrypted using SSH and the rendez-vous server is unable to
|
|
read the contents. The rendez-vous server is nothing more then a glorified bit pipe,
|
|
simply transferring data between end-user SSH client and the agent which runs an
|
|
embedded SSH server.
|
|
</p>
|
|
|
|
<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>
|
|
|
|
<p>
|
|
The agent has more command-line options than shown here.
|
|
Download the agent and run it without arguments to
|
|
see all options.
|
|
</p>
|
|
|
|
<h2>Local clients: using ssh with a proxy command </h2>
|
|
|
|
<p><code>wsproxy</code> is a command that can be used as a proxy command for SSH which performs the connection to the
|
|
remote server. This command needs to be downloaded only once (see <a href="downloads.html">downloads</a>). It does not depend on
|
|
the converge implementation but only on the websocket standards. Other tools that
|
|
provide a mapping of stdio to a websocket can also be used instead of wsproxy.
|
|
</p>
|
|
<p>
|
|
Next step is to run a local SSH or SFTP client:
|
|
</p>
|
|
|
|
<pre>
|
|
{`
|
|
`}ssh -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.HostPort}/client/ID" { access.Username }{"@localhost"} {`
|
|
`}sftp -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.HostPort}/client/ID" { access.Username }{"@localhost"} {`
|
|
`}</pre>
|
|
|
|
<h2>Local clients: using SSH with a local TCP forwarding proxy</h2>
|
|
|
|
<p>
|
|
This option is less convenient than the proxy command because it requires two separate
|
|
commands to execute.
|
|
</p>
|
|
|
|
<p>
|
|
Local clients can connect using regular ssh and sftp commands through a tunnel that
|
|
translates a local TCP port to a websocket connection in converge. See
|
|
the <a href="downloads.html">downloads</a> section.
|
|
This runs a local client that allows SSH to port 10000 and connects to converge using
|
|
a websocket connection.
|
|
</p>
|
|
|
|
|
|
<p>
|
|
Next step is to run a local SSH of SFTP client:
|
|
</p>
|
|
|
|
<pre> {`
|
|
`}ssh -oServerAliveInterval=10 -p 10000 { access.Username }{"@localhost"} {`
|
|
`}sftp -oServerAliveInterval=10 -oPort=10000 { access.Username }{"@localhost"} {`
|
|
`}</pre>
|
|
|
|
<h2>Remote shell usage</h2>
|
|
|
|
<p>
|
|
The agent supports a --shells command-line option by which a comma-separated
|
|
list of shells can be prepended to the default search path for shells, e.g.
|
|
<code>--shells zsh,csh,sh</code> (linux) or <code>cmd,powershell</code> for
|
|
windows.
|
|
</p>
|
|
|
|
<p>
|
|
The agent sets a <coder>agentdir</coder> environment variable that points to
|
|
the directory where the agent is running.
|
|
</p>
|
|
|
|
<h3>Linux</h3>
|
|
|
|
<pre>{`
|
|
# cd back to the agent directory
|
|
cd $agentdir
|
|
|
|
# prevent logout when last user exits
|
|
touch $agentdir/.hold
|
|
`}</pre>
|
|
|
|
<pre>
|
|
</pre>
|
|
|
|
<h3>Windows Command Prompt</h3>
|
|
|
|
<pre>{`
|
|
# cd back to the agent directory
|
|
cd %agentdir%
|
|
|
|
# prevent logout when last user exits
|
|
echo > %agentdir%\.hold
|
|
`}</pre>
|
|
|
|
<h3>Windows Powershell</h3>
|
|
|
|
<pre>{`
|
|
# cd back to the agent directory
|
|
cd $env:agentdir
|
|
|
|
# prevent logout when last user exits
|
|
$null > $env:agentdir\.hold
|
|
`}</pre>
|
|
|
|
<h2>Authentication</h2>
|
|
|
|
<p>
|
|
The <code>{ access.Username }</code> user above is configured in the
|
|
Converge server and is communicated to the agent when the agent is
|
|
started as well as the password.
|
|
</p>
|
|
<p>
|
|
Another way to authenticate is through an .authorized_keys file in the
|
|
same directory as where the agent is started.
|
|
|
|
This can be setup as follows before starting the agent:
|
|
</p>
|
|
<pre> {`
|
|
`}# linux {`
|
|
`}echo "ssh-rsa dkddkdkkk a@b.c" > .authorized_keys {`
|
|
`}echo "ssh-rsa adfadjfdf d@e.f" >> .authorized_keys {`
|
|
`} {`
|
|
`}# windows {`
|
|
`}echo ssh-rsa dkddkdkkk a@b.c > .authorized_keys {`
|
|
`}echo ssh-rsa adfadjfdf d@e.f >> .authorized_keys
|
|
</pre>
|
|
<p>
|
|
Note that on windows you should not used quotes.
|
|
</p>
|
|
|
|
|
|
<script>
|
|
function setCookie(name, value, days) {
|
|
let expires = "";
|
|
if (days) {
|
|
const date = new Date();
|
|
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
expires = "; expires=" + date.toUTCString();
|
|
}
|
|
document.cookie = name + "=" + encodeURIComponent(value) + expires + "; path=/";
|
|
}
|
|
|
|
function getCookie(name) {
|
|
const nameEQ = name + "=";
|
|
const ca = document.cookie.split(';');
|
|
for(let i=0; i < ca.length; i++) {
|
|
let c = ca[i];
|
|
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
|
if (c.indexOf(nameEQ) == 0) return decodeURIComponent(c.substring(nameEQ.length,c.length));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function saveFormToCookie() {
|
|
const form = document.getElementById('inputs');
|
|
const formData = new FormData(form);
|
|
for (let element of form.elements) {
|
|
if (element.id) {
|
|
console.log("Saving " + element.id)
|
|
if (element.type === 'checkbox') {
|
|
console.log("Checkbox " + element.checked)
|
|
setCookie(element.id, element.checked ? 'true' : 'false', 7);
|
|
} else if (element.type === 'radio') {
|
|
if (element.checked) {
|
|
setCookie(element.id, element.value, 7);
|
|
}
|
|
} else {
|
|
setCookie(element.id, element.value, 7);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function loadFormFromCookie() {
|
|
const form = document.getElementById('inputs');
|
|
for (let element of form.elements) {
|
|
if (element.id) {
|
|
const value = getCookie(element.id);
|
|
console.log("Loading " + element.id + " value: " + value)
|
|
if (value !== null) {
|
|
if (element.type === 'checkbox') {
|
|
element.checked = value === 'true';
|
|
} else if (element.type === 'radio') {
|
|
element.checked = (element.value === value);
|
|
} else {
|
|
element.value = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save form data to cookie on change
|
|
document.getElementById('inputs').addEventListener('change', saveFormToCookie);
|
|
|
|
document.body.addEventListener('htmx:load', function(event) {
|
|
loadFormFromCookie();
|
|
});
|
|
|
|
document.body.addEventListener('htmx:afterSettle', function(event) {
|
|
loadFormFromCookie();
|
|
});
|
|
|
|
// when hx-boost=false
|
|
// Load form data from cookie on page load
|
|
//document.addEventListener('DOMContentLoaded', loadFormFromCookie);
|
|
</script>
|
|
|
|
</div>
|
|
}
|
|
|
|
|
|
|
|
templ UsageTab(access models.ConvergeAccess) {
|
|
@BasePage(2) {
|
|
@Usage(access)
|
|
}
|
|
}
|