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

Feature/websockets ssl #34

Merged
merged 7 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ build-*
.DS_Store
*.swp
*.swo
*.bak

# C++ compiler generated files
*.gch
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
#============================================================================
# Initialize the project
#============================================================================
project(ignition-launch1 VERSION 1.6.0)
project(ignition-launch1 VERSION 1.7.0)

#============================================================================
# Find ignition-cmake
Expand Down
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Ignition Launch 1.x

### Ignition Launch 1.7.0 (2020-06-15)

1. Added SSL to websocket server.
* [Pull Request 34](https://github.com/ignitionrobotics/ign-launch/pull/34)

### Ignition Launch 1.6.0 (2020-06-11)

1. Improved websockets by: adding simple authentication, access to
Expand Down
10 changes: 10 additions & 0 deletions examples/websocket.ign
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@
<port>9002</port>
<authorization_key>auth_key</authorization_key>
<admin_authorization_key>admin_key</admin_authorization_key>

<!-- SSL configuration -->
<!-- Specify the path to both the certificate and private key. -->
<!-- Sample self-signed SSL certifacts are located in the
`plugins/websocket_server/` directory with the names `localhost.cert`
and `localhost.key`. -->
<!--<ssl>
<cert_file>PATH_TO_CERT_FILE</cert_file>
<private_key_file>PATH_TO_KEY_FILE</private_key_file>
</ssl> -->
</plugin>

</ignition>
32 changes: 32 additions & 0 deletions plugins/websocket_server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,35 @@ ign launch -f examples/websocket.ign -v 4
```
firefox plugins/websocket_server/index.html
```

# SSL

1. Use the `localhost.cert` and `localhost.key` files for testing purposes.
Configure the websocket plugin using:

```
<ssl>
<cert_file>PATH_TO_localhost.cert</cert_file>
<private_key_file>PATH_TO_localhost.key</private_key_file>
</ssl>
```

* You can create your own self-signed certificates using the following
command. Use "localhost" for the "Common Name" question.

```
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.cert
```

2. Run the plugin.

3. Run a browser, such as firefox, with the `index.html` file.

```
firefox index.html
```

4. Open another browser tab, and go to `https://localhost:9002`. Accept the
certificate.

5. Refresh the `index.html` browser tab.
56 changes: 52 additions & 4 deletions plugins/websocket_server/WebsocketServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,24 @@ bool WebsocketServer::Load(const tinyxml2::XMLElement *_elem)
}
igndbg << "Using port[" << port << "]\n";

std::string sslCertFile = "";
std::string sslPrivateKeyFile = "";
elem = _elem->FirstChildElement("ssl");
if (elem)
{
// Get the ssl cert file, if present.
const tinyxml2::XMLElement *certElem =
elem->FirstChildElement("cert_file");
if (certElem)
sslCertFile = certElem->GetText();

// Get the ssl private key file, if present.
const tinyxml2::XMLElement *keyElem =
elem->FirstChildElement("private_key_file");
if (keyElem)
sslPrivateKeyFile = keyElem->GetText();
}

// All of the protocols handled by this websocket server.
this->protocols.push_back(
{
Expand All @@ -230,7 +248,6 @@ bool WebsocketServer::Load(const tinyxml2::XMLElement *_elem)
// The terminator
this->protocols.push_back({NULL, NULL, 0, 0, 0, 0 });


// We will handle logging
lws_set_log_level( 0, lwsl_emit_syslog);

Expand All @@ -239,9 +256,40 @@ bool WebsocketServer::Load(const tinyxml2::XMLElement *_elem)
info.port = port;
info.iface = NULL;
info.protocols = &this->protocols[0];
// We are not using SSL right now
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;

if (!sslCertFile.empty() && !sslPrivateKeyFile.empty())
{
// Fail if the certificate file cannot be opened.
if (!ignition::common::exists(sslCertFile))
{
ignerr << "SSL certificate file[" << sslCertFile
<< "] does not exist. Quitting.\n";
return false;
}

// Fail if the private key file cannot be opened.
if (!ignition::common::exists(sslPrivateKeyFile))
{
ignerr << "SSL private key file[" << sslPrivateKeyFile
<< "] does not exist. Quitting.\n";
return false;
}

// Store SSL configuration.
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;

info.ssl_cert_filepath = sslCertFile.c_str();
info.ssl_private_key_filepath = sslPrivateKeyFile.c_str();
}
else if (!sslCertFile.empty() || !sslPrivateKeyFile.empty())
nkoenig marked this conversation as resolved.
Show resolved Hide resolved
{
ignwarn << "Partial SSL configuration specified. Please specify: "
<< "\t<ssl>\n"
<< "\t <cert_file>PATH_TO_CERT_FILE</cert_file>\n"
<< "\t <private_key_file>PATH_TO_KEY_FILE</private_key_file>\n"
<< "\t</ssl>.\n"
<< "Continuing without SSL.\n";
}

// keep alive time of 60 seconds
info.ka_time = 60;
Expand Down
23 changes: 20 additions & 3 deletions plugins/websocket_server/WebsocketServer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@ namespace ignition
/// "auth" call on the websocket. If the <authorization_key> is set, then
/// the connection can provide that key.
///
/// * <ssl> : Element that contains SSL configuration. For testing
/// purposes you can create self-signed SSL certificates. Run
///
/// ```
/// openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
/// -keyout server.key -out server.cert
/// ```
///
/// Use "localhost" for the "Common Name" question. If you are testing
/// with a browser, first navigate to "https://localhost:<port>" and
/// accept the self-signed certificate.
///
/// * <cert_file>: Child element of <ssl> that contains the path to
/// the SSL certificate file.
/// * <private_key_file>: Child element of <ssl> that contains the path
/// to SSL private key file.
///
/// # Websocket Server Interface
///
/// The websocket server listens for incoming requests and sends
Expand All @@ -66,7 +83,7 @@ namespace ignition
///
/// The `operation` component is mandatory and must be one of:
/// 1. "sub": Subscribe to the topic in the `topic_name` component,
/// 2. "pub": Publish a message from the Ingition Transport topic in
/// 2. "pub": Publish a message from the Ignition Transport topic in
/// the `topic_name` component,
/// 3. "topics": Get the list of available topics, and
/// 4. "protos": Get a string containing all the protobuf
Expand All @@ -81,7 +98,7 @@ namespace ignition
/// "ignition.msgs.Clock".
///
/// The `payload` component is mandatory for the "pub" operation. If
/// present, it contains a serialized string of an Igntion Message.
/// present, it contains a serialized string of an Ignition Message.
///
/// ## Example frames
///
Expand All @@ -91,7 +108,7 @@ namespace ignition
///
/// 3. Subscribe to the "/clock" topic: `sub,/clock,,`
///
/// 4. Websocker server publishing data on the "/clock" topic:
/// 4. Websocket server publishing data on the "/clock" topic:
/// `pub,/clock,ignition.msgs.Clock,<serialized_data>`
///
/// # Example usage
Expand Down
2 changes: 0 additions & 2 deletions plugins/websocket_server/ign.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ Ignition.prototype.connect = function(url, key) {
/// \brief Emits a 'connection' event on WebSocket connection.
/// \param event - the argument to emit with the event.
function onOpen(event) {
console.log(key);
that.socket.send(buildMsg(['auth','','',key]));
}

Expand Down Expand Up @@ -82,7 +81,6 @@ Ignition.prototype.connect = function(url, key) {
f.onloadend = function(event) {
// This is the proto message data
var contents = event.target.result;
console.log(contents);
if (contents == "authorized") {
that.socket.send(buildMsg(["protos",'','','']));
}
Expand Down
6 changes: 5 additions & 1 deletion plugins/websocket_server/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@

<script>
// Create the Connection to the Ignition websocket server
// This configuration uses SSL and authentication. You can disable both
// by replacing `wss://` with `ws://` and remove the `key` parameter.
// Make sure to also disable SSL and authentication in the
// websocket_server plugin.
var ign = new Ignition({
url: 'ws://localhost:9002',
url: 'wss://localhost:9002',
key: "auth_key"
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the auth key the websocket server expects to receive? Maybe this should be noted in the docs.

This repo does not have the ign.js code in it (and rightly so). Where can I read its source?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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 had put the authorization documentation here: https://github.com/ignitionrobotics/ign-launch/blob/feature/websockets_ssl/plugins/websocket_server/WebsocketServer.hh#L45. I think yout are looking for it in the README.md, which I'll update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated readme: 3273662

});

Expand Down
20 changes: 20 additions & 0 deletions plugins/websocket_server/localhost.cert
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDWzCCAkOgAwIBAgIUBBdTdnPY/LDDrNhlhjxc0zo69pswDQYJKoZIhvcNAQEL
BQAwPTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMSEwHwYDVQQKDBhJbnRlcm5l
dCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAwNjEyMTYxMjU0WhcNMjEwNjEyMTYxMjU0
WjA9MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExITAfBgNVBAoMGEludGVybmV0
IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ANpw7gzpi0vgJKNNmcIeijQmJduEsmoLD79LTKeZ6HvqS6RbkhHT5WADPHIqAfUB
xt+kHuX4CyfdgSidTbLlvfyCKRhkcLhS4GL0p+aZ2uKmb1Nff9jBZ0UMzZmtINgi
bNhoXI/3jXHk5OzxbFcyiw9gawoQGk6Q4aPS0yiX5uXBpRoelDtScC9+ImW/x6B7
4Lx30vPFjsBt+BSjmmcxeAQqybvOPM/pnlmeTalBTRoDojQwNrnkKJqGHP9tnFeT
O0QNoY3//qw0fcT+IWnnXXh3q2dfR03Vk0ZE4vw1WBvSTZoKUJcAcJqzPicktDZg
Jn4jJAse+oJUDvM6NcthBbUCAwEAAaNTMFEwHQYDVR0OBBYEFKN5TH7fFLjQE0wu
rGk0D3XQFloRMB8GA1UdIwQYMBaAFKN5TH7fFLjQE0wurGk0D3XQFloRMA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEX24jK94I15zYG/9XIABLyP
U5AtxS+Xq8wXwLgmhIp+9ST2Q5Ay0pGb7CcmMxCM9rd6G4Ob9HknV85c2PuCElE2
Y+pxdvK9jnrGwoUJOEteOqJ0H9pD5OzBMBF5m1fC85fRUl3DS+Tq92aqCYcqzcRb
K8DSJ2CZLF6XYWklhIs4m62kFjLMkdu9Ew+REGoaCzNW6vFW+E3MSOfJ+M3faP0Z
8nNoUmVgJLIlGPc+3TUHLdbew33jfGXxs2vAno7BFPLYfYL4M0jKjpgsjbA/OtIE
cqwNMVH6wH7vXe7+UAcXmRlwcRGGn0AaOn3neyqwfF4N4fX+JnleZe2WQCFk2F0=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions plugins/websocket_server/localhost.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDacO4M6YtL4CSj
TZnCHoo0JiXbhLJqCw+/S0ynmeh76kukW5IR0+VgAzxyKgH1AcbfpB7l+Asn3YEo
nU2y5b38gikYZHC4UuBi9Kfmmdripm9TX3/YwWdFDM2ZrSDYImzYaFyP941x5OTs
8WxXMosPYGsKEBpOkOGj0tMol+blwaUaHpQ7UnAvfiJlv8ege+C8d9LzxY7AbfgU
o5pnMXgEKsm7zjzP6Z5Znk2pQU0aA6I0MDa55Ciahhz/bZxXkztEDaGN//6sNH3E
/iFp5114d6tnX0dN1ZNGROL8NVgb0k2aClCXAHCasz4nJLQ2YCZ+IyQLHvqCVA7z
OjXLYQW1AgMBAAECggEAXlLDSAoUnyfjSiy5Byx+yvPqBvcuv0GVhCm0qO55iABs
t0TfNxmDg0kCcd2XyL8CrBFHUlAgKQ+ptOrv4R75Qa7GpgTA86a9w50XXyjybkol
6h9jqiohOJzFruUmOI3s6ClwRq5DgnmvLG03NhPaHkKpFchMQ76l4EKp8W5eQrjl
1dVf2n8e6VeGv3IJ2vRp8OimGMsimkfD1TYkmujaMFWhiab2qIraUkfWVexl1wiz
EnYJgjlgQXNb983PiEVHn3KHQOQ7ecMztXeQgUgdAkbc5lR6nwHdMaAsneOuxyND
aq9ZvvPz/cJayluxs4a/2CJG5qH2/ld8028WFGjpxQKBgQD5t2pQyzS3P/D5IW+l
5hHPCmiZkRBzHv20/NCdusnjpLy0j6vKcRBE4rRFAMZzlJJtbtzskvBIStYFnNSs
uG7k38hOfFFqc/2vFK++ybhooPL5NHirLFCW3FaRA0vawUxucc7zEtvZUgHOttiN
6Us9rrmFuiS3lqGjnL+NoF9XZwKBgQDf8AzNTdcO89E5c2s2qUmOzWalqk502+/1
QA/n+aMs6Le2GkzDKHVThRjn7ADohmxiLnpg+Tc/lohWm6LUX6OQokpiUTfsyqFz
DZkGsvU2Jv2pOSOp29dANgd8FQHMylfkxCxhfBgwZPpFUmd8ovZ3JSJAj84XiDX+
3WejFFrUgwKBgQDz2EMc+hFUEEBDRn87xNoHDubtblZd1Blyrp0YKNoUTT1oJBNg
798vJSFbcFJZcu85pVReP24badhsSqTytHa1UEDNQ2BNT06dtNmYuGo24VPiPXbH
z9IyPp7ZpBpiVvdHsiKgAf5kzEuvi6UTjohGh2PqTcak75aPqfTzW3M+aQKBgDMR
6bmAgQU18YcqnU7P+KiKi1hIqK/Z4LWLsJT0x5PcVtk+0jbHqUos1ms91U8yKNGT
S/GFpGXqDJnD0LSiQwkfGdumLhzgcUVt2nI+qdF5vuuyzkFUk5hfOgHAQLLVionv
ezeYN2QCA1l/233/JDozy8Xxhcy0EaxYDeSRJc3FAoGBALXCAnIbgOYx44pDX1vH
dIt7vvpdFxb9VtyQu7fRPc/3cUV5GTr4MmlWBQB3ud7EkrI3PzV7qw/r0kNVrlXO
1fQpkSpm9vU/5R1E0rUlIleX3cOZpZj1KKkhzoD/6ggl24OBJPFzJaHIwJm6XqOX
vfJziO3omKAY8aRAz+TDKWg/
-----END PRIVATE KEY-----