-
Notifications
You must be signed in to change notification settings - Fork 57
Server deployment
The encryption tool is provided as a command line script in Golang, that you can integrate in any workflow you have at your disposal. It's independent from the other LCP pieces (License Server and Status Server, Frontend test Server). You may even decide to take the open-source codebase and create a Web service out of it, with a REST API: this is your freedom as a developer.
It's only linked to the License Server via a REST notification it sends after each encryption; this is why you must care about its command line arguments.
Master files are un-encrypted EPUB files. They must not be visible from the Web, this is an evidence. The LCP License Server must have access to them.
Encrypted files are created by the LCP Encryption Tool and post-processed (moved and renamed) by the LCP License Server. Therefore the repository use to store temporary encrypted files must be accessed both from the Encryption Tool (write access) and the LCP License Server (read access) using the same path.
The final storage of encrypted files must be accessible from the Web, which doesn't cause issues because they are encrypted and the content decryption key is hidden in the LCP License Server database (protected from hackers). It can be a network storage (S3?) or the origin access point of a CDN (Content Delivery Network).
The preferred database for testing purpose is SQLite. But in production mode, it is much better to use a stronger DB like MySQL.
All db structured are automatically created by the server software only if SQLite is in use. If you move to another db, please init the db structures using the scripts found in the dbmodel
folder of the project. The next major version of the software will use an ORM and make this initialization easier plus provide support for other databases.
You have to take care of different aspects:
- HTTPS reverse proxy (SSL layer on top of the unsecure localhost Go server instances, i.e. LSD, frontend running on different ports)
- HTTP route for static file hosting (i.e. repository of encrypted publications, without injected LCP license
META-INF/license.lcpl
) - HTTP port number redirection (optional URL path syntax)
This is the recommended way of treating these aspects.
https://docs.nginx.com/nginx/admin-guide/security-controls/securing-http-traffic-upstream/
Example config:
/etc/nginx/sites-enabled/my.domain.org
HTTPS reverse proxy (SSL layer on top of the unsecure localhost Go server instances, i.e. LCP, LSD, frontend, etc. running on different ports):
server {
listen 80;
server_name my.domain.org;
# http ==> https
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name my.domain.org;
ssl_certificate /etc/ssl/certs/_.domain.org.pem;
ssl_certificate_key /etc/ssl/private/_.domain.org.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
keepalive_timeout 70;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
client_max_body_size 10M;
root /var/www/html;
index index.nginx-debian.html;
location ~* /([0-9]+)/(.*) {
#add_header Cache-Control "public, must-revalidate";
#add_header Strict-Transport-Security "max-age=2592000; includeSubdomains";
proxy_pass http://127.0.0.1:$1/$2$is_args$query_string;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
HTTP route for static file hosting (i.e. repository of encrypted publications, without injected LCP license META-INF/license.lcpl
):
location ~ /files/([0-9a-f-]*) {
alias /PATH_TO_FILES_REPOSITORY/$1;
}
This route corresponds to the publication: "http://127.0.0.1:8989/contents/{publication_id}"
field in the YAML configuration, see: https://github.com/readium/readium-lcp-server/blob/master/README.md#configuration
HTTP port number redirection (optional URL path syntax):
location /url-path {
# extract port number and redirect:
if ($http_referer ~* /([0-9]+)/(.*)) {
set $port $1;
rewrite ^(.*)$ /$port$1 last;
}
}
This redirects the port number expressed as a URL path segment (e.g. domain.org/8801/rest/of/the/url/path
) to the actual IP+port address). The /url-path
location for the URL rewrite is ficticious. In a real-world example based on the README ( https://github.com/readium/readium-lcp-server/blob/master/README.md ), the location would more likely be /api
, e.g. license_link_url: "http://127.0.0.1:8991/api/v1/licenses/{license_id}"
(hypothesis: lcpserver and lsdserver all run from the same machine)
- server IP: 65.65.65.65
- server domain: backend.example.com
<VirtualHost *:80>
ServerName backend.example.com
Redirect permanent / https://backend.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName backend.example.com
ServerAdmin webmaster@localhost
SSLEngine on
SSLProtocol TLSv1.2
SSLHonorCipherOrder on
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
SSLCertificateChainFile "/var/www/ssl/cert-chain.crt"
SSLCertificateFile "/var/www/ssl/cert.crt"
SSLCertificateKeyFile "/var/www/ssl/cert-key.key"
ProxyPreserveHost On
# lcpserver - https://backend.example.com/license/
ProxyPass /license/ http://127.0.0.1:8989/
ProxyPassReverse /license/ http://127.0.0.1:8989/
# lsdserver - https://backend.example.com/status/
ProxyPass /status/ http://127.0.0.1:8990/
ProxyPassReverse /status/ http://127.0.0.1:8990/
# Access to lcpserver is possible only from allowed IP addresses
<Location /license/>
Order deny,allow
Deny from all
Allow from 65.65.65.65
</Location>
</VirtualHost>
Optionally, to block external access to the ports using iptables
:
iptables -A INPUT -p tcp --dport 8989 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 8089 -j DROP
iptables -A INPUT -p tcp --dport 8990 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 8090 -j DROP
After the server is setup and checked internally in "test" mode, after the LCP Terms of Use have been signed, EDRLAb will send some confidential information used to patch the server from "test" mode to "production" mode.
After this is applied, the provider will give EDRLab access to the server for certification. They are several options; the provide can: 1/ give access to a pre-preproduction web server where we can select ebooks, acquire and fetch them or their licence. 2/ give a direct access to the LCP test frontend where we can to the same 3/ give a direct access to the License server (which will be hidden later from the web) 4/ send a pre-defined set of licenses.
Whatever the solution is, EDRLab must get LCP licenses to test all LCP features offered by the server.