Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
50 changes: 50 additions & 0 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,56 @@ CodeCompass_webserver -w <workdir> -p <port> -d <connection_string>

For full documentation see `CodeCompass_webserver -h`.

### Enabling HTTPS (SSL/TLS) secure server

By default, CodeCompass starts a conventional, plain-text HTTP server on the
port specified.
In case a `certificate.pem` file exists under the `--workpace` directory, the
server *will* start in SSL mode.

The certificate file shall be in PEM format, which looks like shown below. If
the certificate you received from your Certificate Authority (or self-created)
isn't in PEM format, use an SSL tool like [OpenSSL](http://openssl.org) to
convert it.

Normally, the private and public key (the certificate) are created as separate
files. They **must** be concatenated to *one* `certificate.pem` file, to look
like the following.
[Further details on SSL](http://github.com/cesanta/mongoose/blob/5.4/docs/SSL.md#how-to-create-ssl-certificate-file)
is available from Mongoose, the library CodeCompass uses for HTTP server.

~~~{.pem}
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAwONaLOP7EdegqjRuQKSDXzvHmFMZfBufjhELhNjo5KsL4ieH
hYN0Zii2yTb63jGxKY6gH1R/r9dL8kXaJmcZrfSa3AgywnteJWg=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDBjCCAe4CCQCX05m0b053QzANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJB
SEGI4JSxV56lYg==
-----END CERTIFICATE-----
~~~

> **Note:** Make sure your certificate file itself is not password-protected,
> as requiring the password to be entered will make the server unable to start
> on its own.

If intermediate certificates are used because your certificate isn't signed
by a Root CA (this is common), the certificate chain's elements (also in, or
converted to PEM format) should also be concatenate into the `certificate.pem`
file:

~~~{.pem}
-----BEGIN RSA PRIVATE KEY-----
Your certificate's private key
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
Your certificate (the public key)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
The certificate of the CA that signed your certificate
-----END CERTIFICATE-----
~~~

### Usage example

```bash
Expand Down
14 changes: 11 additions & 3 deletions service/workspace/src/workspaceservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@ void WorkspaceServiceHandler::getWorkspaces(std::vector<WorkspaceInfo>& _return)
it != fs::directory_iterator();
++it)
{
std::string filename = it->path().filename().native();
if (!fs::is_directory(it->path()))
// Ignore plain files in the workspace directory - projects are always
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can log some warning that the workspace directory contains some irrelevant files.

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 this should be done... the "workspaceservice" should not have authority over what the webserver loads from there, etc. We'd have to duplicate ignoring "authentication.json", "certificate.pem" and potential other files here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we can log some warning that the workspace directory contains some irrelevant files.

The plugin registrar emits warnings in case the project directory does not contain the appropriate project_info.json - it was only workspace service which despite this, sent them name of the project out on the API.

// directories.
continue;
if (!fs::is_regular_file(fs::path{it->path()}.append("project_info.json")))
// Ignore directories that do not have a project information for them.
// (cf. webserver/pluginhelper.h)
continue;

std::string filename = it->path().filename().native();
WorkspaceInfo info;
info.__set_id(filename);
info.__set_description(filename);
info.id = filename;
info.description = filename;

_return.push_back(std::move(info));
}
Expand Down
3 changes: 2 additions & 1 deletion webserver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ set_target_properties(CodeCompass_webserver
PROPERTIES ENABLE_EXPORTS 1)

add_library(mongoose STATIC src/mongoose.c )

target_compile_definitions(mongoose PRIVATE -DNS_ENABLE_SSL)
target_include_directories(mongoose PUBLIC include)
target_compile_options(mongoose PUBLIC -fPIC)
target_link_libraries(mongoose PRIVATE ssl)

target_include_directories(CodeCompass_webserver PUBLIC
include
Expand Down
22 changes: 18 additions & 4 deletions webserver/src/webserver.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include <iostream>

#include <boost/filesystem.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/attr.hpp>
#include <boost/log/attributes.hpp>
#include <boost/program_options.hpp>

#include <util/filesystem.h>
Expand All @@ -12,6 +13,7 @@
#include "threadedmongoose.h"
#include "mainrequesthandler.h"

namespace fs = boost::filesystem;
namespace po = boost::program_options;
namespace trivial = boost::log::trivial;

Expand Down Expand Up @@ -99,9 +101,21 @@ int main(int argc, char* argv[])
server.setOption("listening_port", std::to_string(vm["port"].as<int>()));
server.setOption("document_root", vm["webguiDir"].as<std::string>());

LOG(info)
<< "Mongoose web server starting on port "
<< server.getOption("listening_port");
// Check if certificate.pem exists in the workspace - if so, start SSL.
auto certPath = fs::path(vm["workspace"].as<std::string>()).append("certificate.pem");
if (boost::filesystem::is_regular_file(certPath))
{
LOG(info) << "Starting HTTPS listener based on 'certificate.pem'.";
server.setOption("ssl_certificate", certPath.native());
}
else
{
LOG(warning) << "No 'certificate.pem' found in '--workspace', server "
"running over conventional HTTP!";
}

LOG(info) << "Mongoose web server starting on port "
<< server.getOption("listening_port");

try
{
Expand Down