Initial commit

master
Dennis Schwerdel 2017-01-24 19:55:35 +01:00
commit 914fe1117d
16 changed files with 511 additions and 0 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
.git
.gitignore
.dockerignore
node_modules
screenshots
test

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test/node_modules/

19
CHANGELOG Normal file
View File

@ -0,0 +1,19 @@
[0.1.0]
* Initial version
[0.1.1]
* Update to upstream version 1.10.2.143
[0.1.2]
* Update base image
* Update to upstream version 1.10.3.151
[0.1.3]
* Update post install
[0.2.0]
* Update RainLoop to 1.10.4.183
[0.3.0]
* Update RainLoop to 1.10.5.192

27
CloudronManifest.json Normal file
View File

@ -0,0 +1,27 @@
{
"id": "org.apache.incubator.guacamole.cloudronapp",
"title": "Goacamole",
"author": "Apache Software Foundation",
"description": "file://DESCRIPTION.md",
"changelog": "file://CHANGELOG",
"tagline": "Apache Guacamole is a clientless remote desktop gateway. It supports standard protocols like VNC, RDP, and SSH.",
"version": "0.1.0",
"healthCheckPath": "/",
"httpPort": 8080,
"addons": {
"mysql": {},
"ldap": {}
},
"developmentMode": false,
"manifestVersion": 1,
"website": "http://guacamole.incubator.apache.org/",
"contactEmail": "support@cloudron.io",
"icon": "logo.png",
"tags": [
"vnc", "rdp", "ssh", "rdesktop"
],
"mediaLinks": [
"file:///screenshots/1.jpg"
],
"postInstallMessage": "file://POSTINSTALL.md"
}

53
DESCRIPTION.md Normal file
View File

@ -0,0 +1,53 @@
This app packages Guacamole 0.9.10-incubating.
Apache Guacamole is a clientless remote desktop gateway. It supports standard protocols like VNC, RDP, and SSH.
#### What is Guacamole?
Guacamole is an HTML5 web application that provides access to desktop environments using remote desktop protocols (such as VNC or RDP). Guacamole is also the project that produces this web application, and provides an API that drives it. This API can be used to power other similar applications or services.
"Guacamole" is most commonly used to refer to the web application produced by the Guacamole project using their API. This web application is part of a stack that provides a protocol-agnostic remote desktop gateway. Written in JavaScript and using only HTML5 and other standards, the client part of Guacamole requires nothing more than a modern web browser or web-enabled device when accessing any of the desktops served.
Historically, Guacamole was an HTML5 VNC client, and before that, a JavaScript Telnet client called RealMint ("RealMint" is an anagram for "terminal"), but this is no longer the case. Guacamole's architecture has grown to encompass remote desktop in general, and can be used as a gateway for any number of computers. Originally a proof-of-concept, Guacamole is now performant enough for daily use, and all Guacamole development is done over Guacamole.
As an API, Guacamole provides a common and efficient means of streaming text data over a JavaScript-based tunnel using either HTTP or WebSocket, and a client implementation which supports the Guacamole protocol and renders the remote display when combined with a Guacamole protocol stream from the tunnel.
It provides cross-browser mouse and keyboard events, an XML-driven on-screen keyboard, and synchronized nestable layers with hardware-accelerated compositing. Projects that wish to provide remote desktop support over HTML5 can leverage the years of research and development that went into Guacamole by incorporating the API into their application or service.
#### Why use Guacamole?
The principle reason to use Guacamole is constant, world-wide, unfettered access to your computers.
Guacamole allows access one or more desktops from anywhere remotely, without having to install a client, particularly when installing a client is not possible. By setting up a Guacamole server, you can provide access to any other computer on the network from virtually any other computer on the internet, anywhere in the world. Even mobile phones or tablets can be used, without having to install anything.
As a true web application whose communication is over HTTP or HTTPS only, Guacamole allows you to access your machines from anywhere without violating the policy of your workplace, and without requiring the installation of special clients. The presence of a proxy or corporate firewall does not prevent Guacamole use.
#### Access your computers from any device
As Guacamole requires only a reasonably-fast, standards-compliant browser, Guacamole will run on many devices, including mobile phones and tablets.
Guacamole is specifically designed to not care whether you have a mouse, keyboard, touchscreen, or any combination of those.
One of the major design philosophies behind Guacamole is that it should never assume you have a particular device (ie: a mobile phone) just because your browser has or is missing a specific feature (ie: touch events or a smallish screen). Guacamole's codebase provides support for both mouse and touch events simultaneously, without choosing one over the other, while the interface is intended to be usable regardless of screen size.
Barring bugs, you should be able to use Guacamole on just about any modern device with a web browser.
#### Keep a computer in the "cloud"
Ignoring the buzzword, it's often useful to have a computer that has no dedicated physical hardware, where its processing and storage power are handled transparently by redundant systems in some remote datacenter.
Computers hosted on virtualized hardware are more resilient to failures, and with so many companies now offering on-demand computing resources, Guacamole is a perfect way to access several machines that are only accessible over the internet.
In fact, all Guacamole development is done on computers like this. This is partly because we like the mobility, and partly because we want to ensure Guacamole is always performant enough for daily use.
#### Provide easy access to a group
Guacamole allows you to centralize access to a large group of machines, and specify on a per-user basis which machines are accessible. Rather than remember a list of machines and credentials, users need only log into a central server and click on one of the connections listed.
If you have multiple computers which you would like to access remotely, or you are part of a group where each person has a set of machines that they need remote access to, Guacamole is a good way to provide that access while also ensuring that access is available from anywhere.
#### Adding HTML5 remote access to your existing infrastructure
As Guacamole is an API, not just a web application, the core components and libraries provided by the Guacamole project can be used to add HTML5 remote access features to an existing application. You need not use the main Guacamole web application; you can write (or integrate with) your own rather easily.
If you host an on-demand computing service, adding HTML5-based remote access allows users of your service more broad access; users need nothing more than a web browser to see their computers' screens.

57
Dockerfile Normal file
View File

@ -0,0 +1,57 @@
FROM cloudron/base:0.9.0
MAINTAINER Guacamole Developers <support@cloudron.io>
EXPOSE 8000
RUN apt-get update \
&& apt-get -y install libcairo2-dev libjpeg-turbo8-dev libpng12-dev libossp-uuid-dev \
libavcodec-dev libavutil-dev libswscale-dev libfreerdp-dev libpango1.0-dev libssh2-1-dev \
libtelnet-dev libvncserver-dev libpulse-dev libssl-dev libvorbis-dev libwebp-dev \
tomcat8 freerdp ghostscript
ENV VERSION 0.9.10-incubating
ENV MYSQL_CONNECTOR_VERSION 5.1.40
ENV DOWNLOAD_URL "http://apache.org/dyn/closer.cgi?action=download&filename=incubator/guacamole/${VERSION}"
RUN mkdir -p /app/code
WORKDIR /app/code
# Compile the server
RUN wget "$DOWNLOAD_URL/source/guacamole-server-${VERSION}.tar.gz" -O - | tar -xz \
&& cd guacamole-server-${VERSION} \
&& ./configure --prefix=/app/code \
&& make \
&& make install \
&& cd .. \
&& rm -rf guacamole-server-${VERSION}
# Download extensions
RUN mkdir -p /app/code/extensions \
&& wget "$DOWNLOAD_URL/binary/guacamole-auth-ldap-${VERSION}.tar.gz" -O - | tar -xz \
&& wget "$DOWNLOAD_URL/binary/guacamole-auth-jdbc-${VERSION}.tar.gz" -O - | tar -xz \
&& mv guacamole-auth-ldap-${VERSION}/guacamole-auth-ldap-${VERSION}.jar /app/code/extensions \
&& mv guacamole-auth-jdbc-${VERSION}/mysql/guacamole-auth-jdbc-mysql-${VERSION}.jar /app/code/extensions \
&& mv guacamole-auth-jdbc-${VERSION}/mysql/schema /app/code/schema \
&& rm -rf guacamole-auth-ldap-${VERSION} guacamole-auth-jdbc-${VERSION}
# Download MySQL connector
RUN mkdir -p /app/code/lib \
&& wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-${MYSQL_CONNECTOR_VERSION}.tar.gz -O - | tar -xz \
&& mv mysql-connector-java-${MYSQL_CONNECTOR_VERSION}/mysql-connector-java-${MYSQL_CONNECTOR_VERSION}-bin.jar /app/code/lib \
&& rm -rf mysql-connector-java-${MYSQL_CONNECTOR_VERSION}
# Get WAR app
RUN mkdir -p /app/code/war \
&& wget "$DOWNLOAD_URL/binary/guacamole-${VERSION}.war" -O /app/code/war/ROOT.war \
&& ln -s /app/code/war /usr/share/tomcat8/webapps
# Configure Tomcat
RUN ln -s /run/tomcat/temp /usr/share/tomcat8/temp \
&& ln -s /etc/tomcat8 /usr/share/tomcat8/conf \
&& ln -s /run/guacamole/guacamole.properties /app/code/guacamole.properties
ENV GUACAMOLE_HOME /app/code
ADD start.sh /app/code/start.sh
CMD [ "/app/code/start.sh" ]

9
LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License (MIT)
Copyright (c) 2016 Cloudron UG
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

8
POSTINSTALL.md Normal file
View File

@ -0,0 +1,8 @@
This application integrates with Cloudron authentication.
To store connection data of custom permissions for Cloudron users, a Guacamole account with the same username needs to be created.
There is a default admin user in Guacamole with the following credentials:
* Username: `guacadmin`
* Password: `guacadmin` (please change that password immediatly)

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# Minio Cloudron App
This repository contains the Cloudron app package source for [Minio](http://www.minio.io/).
## Installation
[![Install](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=io.minio.cloudronapp)
or using the [Cloudron command line tooling](https://cloudron.io/references/cli.html)
```
cloudron install --appstore-id io.minio.cloudronapp
```
## Building
The app package can be built using the [Cloudron command line tooling](https://cloudron.io/references/cli.html).
```
cd minio-app
cloudron build
cloudron install
```
## Testing
The e2e tests are located in the `test/` folder and require [nodejs](http://nodejs.org/). They are creating a fresh build, install the app on your Cloudron, perform tests, backup, restore and test if the repos are still ok. The tests expect port 29418 to be available.
```
cd minio-app/test
npm install
export PATH=$PATH:node_modules/.bin
mocha --bail test.js
```

75
config.json Normal file
View File

@ -0,0 +1,75 @@
{
"version": "10",
"credential": {
"accessKey": "admin",
"secretKey": "secretkey"
},
"region": "us-east-1",
"logger": {
"console": {
"enable": true,
"level": "error"
},
"file": {
"enable": false,
"fileName": "",
"level": ""
}
},
"notify": {
"amqp": {
"1": {
"enable": false,
"url": "",
"exchange": "",
"routingKey": "",
"exchangeType": "",
"mandatory": false,
"immediate": false,
"durable": false,
"internal": false,
"noWait": false,
"autoDeleted": false
}
},
"nats": {
"1": {
"enable": false,
"address": "",
"subject": "",
"username": "",
"password": "",
"token": "",
"secure": false,
"pingInterval": 0
}
},
"elasticsearch": {
"1": {
"enable": false,
"url": "",
"index": ""
}
},
"redis": {
"1": {
"enable": false,
"address": "",
"password": "",
"key": ""
}
},
"postgresql": {
"1": {
"enable": false,
"connectionString": "",
"table": "",
"host": "",
"port": "",
"user": "",
"password": "",
"database": ""
}
}
}
}

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
screenshots/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

31
start.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
set -eu
mkdir -p /run/guacamole
cat > /run/guacamole/guacamole.properties <<EOF
ldap-hostname=${LDAP_SERVER}
ldap-port=${LDAP_PORT}
ldap-search-bind-dn=${LDAP_BIND_DN}
ldap-search-bind-password=${LDAP_BIND_PASSWORD}
ldap-user-base-dn=${LDAP_USERS_BASE_DN}
ldap-group-base-dn=${LDAP_GROUPS_BASE_DN}
ldap-username-attribute:username
mysql-hostname=${MYSQL_HOST}
mysql-port=${MYSQL_PORT}
mysql-database=${MYSQL_DATABASE}
mysql-username=${MYSQL_USERNAME}
mysql-password=${MYSQL_PASSWORD}
EOF
mkdir -p /run/tomcat/temp
MYSQL="mysql -u ${MYSQL_USERNAME} -p${MYSQL_PASSWORD} -h ${MYSQL_HOST} --port ${MYSQL_PORT} --database ${MYSQL_DATABASE}"
$MYSQL < /app/code/schema/001-create-schema.sql \
&& $MYSQL < /app/code/schema/002-create-admin-user.sql \
|| true
/app/code/sbin/guacd
exec /usr/share/tomcat8/bin/catalina.sh run

7
test/.jshintrc Normal file
View File

@ -0,0 +1,7 @@
{
"node": true,
"browser": true,
"unused": true,
"globalstrict": true,
"predef": [ "angular", "$", "describe", "it", "before", "after" ]
}

21
test/package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^2.4.2",
"expect.js": "^0.3.1",
"mkdirp": "^0.5.1",
"mocha": "^2.5.3",
"rimraf": "^2.5.3",
"selenium-server-standalone-jar": "^2.53.1",
"selenium-webdriver": "^2.53.3",
"superagent": "^1.4.0"
}
}

159
test/test.js Normal file
View File

@ -0,0 +1,159 @@
#!/usr/bin/env node
'use strict';
var execSync = require('child_process').execSync,
expect = require('expect.js'),
path = require('path'),
webdriver = require('selenium-webdriver');
var by = webdriver.By,
until = webdriver.until;
var accessKey = 'admin',
secretKey = 'secretkey';
var bucket_prefix = 'bucket',
bucket_id = 0,
bucket;
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
describe('Application life cycle test', function () {
this.timeout(0);
var chrome = require('selenium-webdriver/chrome');
var server, browser = new chrome.Driver();
before(function (done) {
var seleniumJar= require('selenium-server-standalone-jar');
var SeleniumServer = require('selenium-webdriver/remote').SeleniumServer;
server = new SeleniumServer(seleniumJar.path, { port: 4444 });
server.start();
done();
});
after(function (done) {
browser.quit();
server.stop();
done();
});
var LOCATION = 'minio-test';
var TEST_TIMEOUT = 10000;
var app;
function pageLoaded(callback) {
return browser.wait(until.elementLocated(by.className('page-load pl-0 pl-1')), TEST_TIMEOUT).then(function () {
callback();
});
}
function visible(selector, callback) {
return browser.wait(until.elementLocated(selector), TEST_TIMEOUT).then(function () {
browser.wait(until.elementIsVisible(browser.findElement(selector)), TEST_TIMEOUT).then(function () {
callback();
});
});
}
function login(callback) {
browser.manage().deleteAllCookies();
browser.get('https://' + app.fqdn);
visible(by.id('accessKey'), function () {
browser.findElement(by.id('accessKey')).sendKeys(accessKey);
browser.findElement(by.id('secretKey')).sendKeys(secretKey);
browser.findElement(by.className('lw-btn')).click();
browser.wait(until.elementLocated(by.id('top-right-menu')), TEST_TIMEOUT).then(function () { callback(); });
});
}
function logout(callback) {
browser.get('https://' + app.fqdn);
pageLoaded(function () {
visible(by.id('top-right-menu'), function () {
browser.findElement(by.id('top-right-menu')).click();
visible(by.xpath('//*[text()="Sign Out "]'), function () {
browser.findElement(by.xpath('//*[text()="Sign Out "]')).click();
browser.wait(until.elementLocated(by.id('accessKey')), TEST_TIMEOUT).then(function () { callback(); });
});
});
});
}
function addBucket(callback) {
bucket_id = bucket_id + 1;
bucket = bucket_prefix + bucket_id;
browser.get('https://' + app.fqdn);
pageLoaded(function () {
visible(by.className('fa fa-plus'), function () {
browser.findElement(by.className('fa fa-plus')).click();
visible(by.className('fa fa-hdd-o'), function () {
browser.findElement(by.className('fa fa-hdd-o')).click();
visible(by.xpath('//*[@class="modal-body"]/form/div/input'), function() {
browser.findElement(by.xpath('//*[@class="modal-body"]/form/div/input')).sendKeys(bucket);
browser.findElement(by.xpath('//*[@class="modal-body"]/form')).submit();
visible(by.xpath('//*[@class="main"]/a[text()="' + bucket + '"]'), function() {
callback();
});
});
});
});
});
}
xit('build app', function () {
execSync('cloudron build', { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' });
});
it('install app', function () {
execSync('cloudron install --new --wait --location ' + LOCATION, { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' });
});
it('can get app information', function () {
var inspect = JSON.parse(execSync('cloudron inspect'));
app = inspect.apps.filter(function (a) { return a.location === LOCATION; })[0];
expect(app).to.be.an('object');
});
it('can login', login);
it('can add buckets', addBucket);
it('can logout', logout);
it('backup app', function () {
execSync('cloudron backup create --app ' + app.id, { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' });
});
it('restore app', function () {
execSync('cloudron restore --app ' + app.id, { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' });
});
it('can login', login);
it('can add buckets', addBucket);
it('can logout', logout);
it('move to different location', function () {
browser.manage().deleteAllCookies();
execSync('cloudron install --location ' + LOCATION + '2', { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' });
var inspect = JSON.parse(execSync('cloudron inspect'));
app = inspect.apps.filter(function (a) { return a.location === LOCATION + '2'; })[0];
expect(app).to.be.an('object');
});
it('can login', login);
it('can add buckets', addBucket);
it('can logout', logout);
it('uninstall app', function () {
execSync('cloudron uninstall --app ' + app.id, { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' });
});
});