Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Login directly to remote machines #5118

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 11 additions & 5 deletions doc/authentication.md
Expand Up @@ -95,17 +95,23 @@ speaking the cockpit protocol on stdin and stdout.
# SSH Logins

The ```remote-login-ssh``` action uses ssh to authenticate the user and and launch a bridge.
Currently this should only be used with basic authentication.

For example

```
[basic]
action = remote-login-ssh
host = 10.10.122.12
```

If not provided host will default to 127.0.0.1
Cockpit will also default to using ssh when a remote machine is provided by using a application
name that begins with ```cockpit+=```.

The section ```SSH-Login``` defines the options for all ssh commands. The section takes
has the same options as the other authentication sections with the following additions.

* ```host``` The default host to log into. Defaults to 127.0.0.1.
* ```allowUnknown```. By default cockpit will refuse to connect to any machines that
are not already present in it's known_hosts file (usually ```/var/lib/cockpit/known_hosts```).
Set this to ```true``` is to allow those connections to proceed.


# None

Expand Down
39 changes: 34 additions & 5 deletions doc/urls.md
Expand Up @@ -6,10 +6,18 @@ This is developer documentation about the various resource paths in Cockpit
and their characteristics. This doesn't apply to the visible URLs shown
in the main Cockpit address bar.

Cockpit URLs are based on an application. A valid application name is
either the word ```cockpit``` or a string that begins with ```cockpit+```
for example ```cockpit+application-name```. Each of the following URLs
are valid for any application, just replace ```/cockpit/``` with ```/cockpit+application-name/```

* ```/cockpit/static``` static files available without authentication. Files
are cached for as long as possible, and names *must* change when the
contents of the file changes.

* ```/cockpit/login``` authenticates a user and sets cookie based on application
name.

* ```/cockpit/$xxxxxxxxxxxxxxx/package/path/to/file.ext``` are files which
are cached by packages for as long as possible. The checksum changes when
any of the packages on a system change. Only available after authentication.
Expand All @@ -23,12 +31,33 @@ in the main Cockpit address bar.
* ```/cockpit/@host/manifests.js``` includes a summary of all the manifest
files from all the packages, as an AMD loadable module

* ```/cockpit+embedder/$host/package/...``` an embedder identifier can be
included in the path.

* ```/cockpit/socket``` The main web socket

* ```/cockpit/channel/csrftoken?query``` External channel URLs

* If loading through cockpit-ws ... any other URL that starts with
a possible host name or package name will be handled by shell/index.html.
When loading through cockpit-ws any URL that does not begin with an
application will be handled by the shell (shell/index.html by default)
using the default application ```cockpit```.


Direct to machine urls
======================

Cockpit-ws supports logging in directly to a remote machine, without first
authenticating on the machine that cockpit-ws is running on. A cockpit-ssh
processes is spawned that connects via SSH to the remote machine and all
requests are proxied via that connection.

To use this feature the application name MUST begin with an ```=``` for
example ```/cockpit+=machine/socket``` will attempt to open a socket on
```machine``` ```/cockpit+machine/socket``` will attempt to open a socket
on localhost.

When loading through cockpit-ws any URL that does not begin with an
application will be handled by the shell (shell/index.html by default)
using the default application ```cockpit```.

In addition any url that begins with ```/=``` will attempt to load
the shell from the specified machine. For example a URL of
```/=machine/system``` will attempt to load ```shell/index.html```
from ```machine``` using the application ```cockpit+machine```.
24 changes: 17 additions & 7 deletions lib/machines.js
Expand Up @@ -21,10 +21,12 @@
* overlay: extra data to augment and override on top of content
* }
*
* This is the sessionStorage key at which the data is placed.
* This uses sessionStorage rather than cockpit.sessionStorage
* because we don't ever want to write unprefixed keys.
*/
var key = "v2-machines.json";
var session_prefix = "v1-session-machine";

var key = cockpit.sessionStorage.prefixedKey("v2-machines.json");
var session_prefix = cockpit.sessionStorage.prefixedKey("v1-session-machine");

function generate_session_key(host) {
return session_prefix + "/" + host;
Expand Down Expand Up @@ -81,6 +83,9 @@
}

function refresh(shared, push) {
if (!shared)
return;

var emit_ready = !self.ready;

self.ready = true;
Expand All @@ -104,7 +109,7 @@

var events = [];

var machine;
var machine, application;
for (host in hosts) {
var old_machine = machines[host] || { };
var old_conns = old_machine.connection_string;
Expand All @@ -125,10 +130,15 @@
machine.address);

if (!machine.label) {
if (host == "localhost" || host == "localhost.localdomain")
machine.label = window.location.hostname;
else
if (host == "localhost" || host == "localhost.localdomain") {
application = cockpit.transport.application();
if (application.indexOf('cockpit+=') === 0)
machine.label = application.replace('cockpit+=', '');
else
machine.label = window.location.hostname;
} else {
machine.label = host;
}
}
if (!machine.avatar)
machine.avatar = "../shell/images/server-small.png";
Expand Down
2 changes: 1 addition & 1 deletion pkg/dashboard/manifest.json
@@ -1,7 +1,7 @@
{
"version": "@VERSION@",
"requires": {
"cockpit": "118"
"cockpit": "119.x"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a cockpit.spec change too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think dashboard ever has it's own package

},

"dashboard": {
Expand Down
19 changes: 17 additions & 2 deletions pkg/kubernetes/scripts/kube-client-cockpit.js
Expand Up @@ -883,15 +883,16 @@
"CockpitKubeRequest",
"cockpitKubectlConfig",
"cockpitConnectionInfo",
function($q, CockpitKubeRequest, cockpitKubectlConfig, info) {
"cockpitBrowserStorage",
function($q, CockpitKubeRequest, cockpitKubectlConfig, info, browser) {
var defer = null;

return function cockpitKubeDiscover(force) {
if (!force && defer)
return defer.promise;

var last, req, kubectl, loginOptions;
var loginData = window.localStorage.getItem('login-data');
var loginData = browser.localStorage.getItem('login-data', true);
defer = $q.defer();

var schemes = [
Expand Down Expand Up @@ -1113,6 +1114,20 @@
}
])

.factory("cockpitBrowserStorage", [
"$window",
function($window) {
var base = $window;
if (cockpit && cockpit.sessionStorage && cockpit.localStorage)
base = cockpit;

return {
sessionStorage: base.sessionStorage,
localStorage: base.localStorage
};
}
])

.factory('cockpitConnectionInfo', function () {
return {
type: null,
Expand Down
4 changes: 3 additions & 1 deletion pkg/kubernetes/scripts/main.js
Expand Up @@ -74,11 +74,12 @@
'KubeFormatProvider',
'kubernetesContainerSocketProvider',
'KubeDiscoverSettingsProvider',
'KubeBrowserStorageProvider',
'$provide',
function($routeProvider, KubeWatchProvider, KubeRequestProvider,
KubeSocketProvider, KubeTranslateProvider, KubeFormatProvider,
kubernetesContainerSocketProvider, KubeDiscoverSettingsProvider,
$provide) {
KubeBrowserStorageProvider, $provide) {

$routeProvider.otherwise({ redirectTo: '/' });

Expand All @@ -89,6 +90,7 @@
KubeTranslateProvider.KubeTranslateFactory = "CockpitTranslate";
KubeFormatProvider.KubeFormatFactory = "CockpitFormat";
KubeDiscoverSettingsProvider.KubeDiscoverSettingsFactory = "cockpitKubeDiscoverSettings";
KubeBrowserStorageProvider.KubeBrowserStorageFactory = "cockpitBrowserStorage";

/* Tell the container-terminal that we want to be involved in WebSocket creation */
kubernetesContainerSocketProvider.WebSocketFactory = 'cockpitContainerWebSocket';
Expand Down
8 changes: 4 additions & 4 deletions pkg/kubernetes/scripts/nodes.js
Expand Up @@ -87,10 +87,10 @@
'nodeData',
'nodeStatsSummary',
'$timeout',
'$window',
'KubeBrowserStorage',
function($scope, loader, select, ListingState, filterService,
$routeParams, $location, actions, nodeData, statsSummary,
$timeout, $window) {
$timeout, browser) {
var target = $routeParams["target"] || "";
$scope.target = target;

Expand Down Expand Up @@ -162,7 +162,7 @@
};

$scope.jump = function (node) {
var host, key, ip;
var host, ip;
if (!node || !node.spec)
return;

Expand All @@ -172,7 +172,7 @@
if (ip == "127.0.0.1" || ip == "::1") {
ip = "localhost";
} else {
$window.sessionStorage.setItem(
browser.sessionStorage.setItem(
"v1-session-machine/" + ip,
JSON.stringify({"address": ip,
"label": host,
Expand Down
33 changes: 33 additions & 0 deletions pkg/kubernetes/scripts/utils.js
Expand Up @@ -143,6 +143,39 @@
}
])

.provider('KubeBrowserStorage', [
function() {
var self = this;

/* Until we come up with a good default implementation, must be provided */
self.KubeBrowserStorageFactory = "DefaultKubeBrowserStorage";

function load(injector, name) {
if (angular.isString(name))
return injector.get(name, "DefaultKubeBrowserStorage");
else
return injector.invoke(name);
}

self.$get = [
"$injector",
function($injector) {
return load($injector, self.KubeBrowserStorageFactory);
}
];
}
])

.factory("DefaultKubeBrowserStorage", [
"$window",
function($window) {
return {
localStorage: $window.localStorage,
sessionStorage: $window.sessionStorage,
};
}
])

.filter('formatCapacityName', function() {
return function(key) {
var data;
Expand Down
2 changes: 1 addition & 1 deletion pkg/shell/index-no-machines.js
Expand Up @@ -41,7 +41,7 @@ var phantom_checkpoint = phantom_checkpoint || function () { };
default_title: default_title
});

var login_data = window.localStorage.getItem('login-data');
var login_data = cockpit.localStorage.getItem('login-data', true);
if (login_data) {
var data = JSON.parse(login_data);
$("#content-user-name").text(data["displayName"]);
Expand Down
2 changes: 1 addition & 1 deletion pkg/shell/index-stub.js
Expand Up @@ -60,7 +60,7 @@

indexes.machines_index(options, machines, loader, dialogs);

var login_data = window.localStorage.getItem('login-data');
var login_data = cockpit.localStorage.getItem('login-data', true);
if (login_data) {
var data = JSON.parse(login_data);
$("#content-user-name").text(data["displayName"]);
Expand Down
5 changes: 2 additions & 3 deletions pkg/shell/indexes.js
Expand Up @@ -59,7 +59,7 @@ var phantom_checkpoint = phantom_checkpoint || function () { };
/* Reconnect button */
$("#machine-reconnect").on("click", function(ev) {
if (watchdog_problem) {
window.sessionStorage.clear();
cockpit.sessionStorage.clear();
window.location.reload(true);
} else {
navigate(null, true);
Expand Down Expand Up @@ -482,7 +482,7 @@ var phantom_checkpoint = phantom_checkpoint || function () { };

/* Reconnect button */
$("#machine-reconnect").on("click", function(ev) {
window.sessionStorage.clear();
cockpit.sessionStorage.clear();
window.location.reload(true);
});

Expand Down Expand Up @@ -612,4 +612,3 @@ var phantom_checkpoint = phantom_checkpoint || function () { };
}

}());

1 change: 1 addition & 0 deletions src/base1/Makefile.am
Expand Up @@ -79,6 +79,7 @@ base_TESTS = \
src/base1/test-framed-cache.html \
src/base1/test-websocket.html \
src/base1/test-stub.html \
src/base1/test-browser-storage.html \
$(NULL)

TESTS += $(base_TESTS)
Expand Down