Commit 1ee608c4 authored by Stratos Psomadakis's avatar Stratos Psomadakis
Browse files

Encrypt instance ids in the stats URLs

parent 597404ab
...@@ -173,6 +173,14 @@ Cyclades ...@@ -173,6 +173,14 @@ Cyclades
'service-export-cyclades'. 'service-export-cyclades'.
* Obsolete PUBLIC_USE_POOL setting, since Cyclades manages IP pool for all * Obsolete PUBLIC_USE_POOL setting, since Cyclades manages IP pool for all
type of networks. type of networks.
* Encrypt / decrypt the instance id / hostname in the stats URL in
snf-cyclades-app and snf-stats-app, using the 'CYCLADES_STATS_SECRET_KEY'
and 'STATS_SECRET_KEY' respectively.
* Add support for snf-vncauthproxy-1.5 and the setting
'CYCLADES_VNCAUTHPROXY_OPTS', which configures the extra options / arguments
needed by the newer version of snf-vncauthproxy. Support for older versions
of snf-vncauthproxy has been dropped. See also the upgrade notes for Synnefo
and snf-vncauthproxy-1.5.
Pithos Pithos
------ ------
...@@ -342,6 +350,7 @@ Cyclades ...@@ -342,6 +350,7 @@ Cyclades
of the pool of Pithos backends that are used by plankton. of the pool of Pithos backends that are used by plankton.
.. _Changelog-0.14: .. _Changelog-0.14:
v0.14 v0.14
......
...@@ -161,6 +161,14 @@ For Pithos service we have to change the ``20-snf-pithos-app-settings.conf`` ...@@ -161,6 +161,14 @@ For Pithos service we have to change the ``20-snf-pithos-app-settings.conf``
file in the same way as above. file in the same way as above.
v0.15 has also introduced the ``CYCLADES_STATS_SECRET_KEY`` and
``STATS_SECRET_KEY`` settings. ``CYCLADES_STATS_SECRET_KEY`` in
``20-snf-cyclades-app-api.conf`` is used by Cyclades to encrypt the instance id
/ hostname in the URLs serving the VM stats. You should set it to a random
value / string and make sure that it's the same as the ``STATS_SECRET_KEY``
setting (used to decrypt the instance hostname) in
``20-snf-stats-settings.conf`` on your Stats host.
3. Create floating IP pools 3. Create floating IP pools
=========================== ===========================
......
...@@ -85,13 +85,17 @@ ...@@ -85,13 +85,17 @@
#BACKEND_PER_USER = {} #BACKEND_PER_USER = {}
# #
# #
## Encryption key for the instance hostname in the stat graphs URLs. Set it to
## a random string and update the STATS_SECRET_KEY setting in the snf-stats-app
## host (20-snf-stats-app-settings.conf) accordingly.
#CYCLADES_STATS_SECRET_KEY = "secret key"
#
## URL templates for the stat graphs. ## URL templates for the stat graphs.
## The API implementation replaces '%s' with the encrypted backend id. ## The API implementation replaces '%s' with the encrypted backend id.
## FIXME: For now we do not encrypt the backend id. #CPU_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-bar/%s'
#CPU_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-bar.png' #CPU_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-ts/%s'
#CPU_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-ts.png' #NET_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/net-bar/stats/v1.0/%s'
#NET_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/net-bar.png' #NET_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/net-ts/%s'
#NET_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/net-ts.png'
# #
## Recommended refresh period for server stats ## Recommended refresh period for server stats
#STATS_REFRESH_PERIOD = 60 #STATS_REFRESH_PERIOD = 60
......
...@@ -687,8 +687,7 @@ def server_stats(request, server_id): ...@@ -687,8 +687,7 @@ def server_stats(request, server_id):
log.debug('server_stats %s', server_id) log.debug('server_stats %s', server_id)
vm = util.get_vm(server_id, request.user_uniq) vm = util.get_vm(server_id, request.user_uniq)
#secret = util.encrypt(vm.backend_vm_id) secret = util.stats_encrypt(vm.backend_vm_id)
secret = vm.backend_vm_id # XXX disable backend id encryption
stats = { stats = {
'serverRef': vm.id, 'serverRef': vm.id,
......
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
# interpreted as representing official policies, either expressed # interpreted as representing official policies, either expressed
# or implied, of GRNET S.A. # or implied, of GRNET S.A.
from base64 import b64encode, b64decode from base64 import urlsafe_b64encode, b64decode
from urllib import quote
from hashlib import sha256 from hashlib import sha256
from logging import getLogger from logging import getLogger
from random import choice from random import choice
...@@ -118,13 +119,13 @@ def zeropad(s): ...@@ -118,13 +119,13 @@ def zeropad(s):
return s + '\x00' * npad return s + '\x00' * npad
def encrypt(plaintext): def stats_encrypt(plaintext):
# Make sure key is 32 bytes long # Make sure key is 32 bytes long
key = sha256(settings.SECRET_KEY).digest() key = sha256(settings.CYCLADES_STATS_SECRET_KEY).digest()
aes = AES.new(key) aes = AES.new(key)
enc = aes.encrypt(zeropad(plaintext)) enc = aes.encrypt(zeropad(plaintext))
return b64encode(enc) return quote(urlsafe_b64encode(enc))
def get_vm(server_id, user_id, for_update=False, non_deleted=False, def get_vm(server_id, user_id, for_update=False, non_deleted=False,
......
...@@ -84,13 +84,17 @@ DEFAULT_FIREWALL_PROFILE = 'DISABLED' ...@@ -84,13 +84,17 @@ DEFAULT_FIREWALL_PROFILE = 'DISABLED'
BACKEND_PER_USER = {} BACKEND_PER_USER = {}
# Encryption key for the instance hostname in the stat graphs URLs. Set it to
# a random string and update the STATS_SECRET_KEY setting in the snf-stats-app
# host (20-snf-stats-app-settings.conf) accordingly.
CYCLADES_STATS_SECRET_KEY = "secret_key"
# URL templates for the stat graphs. # URL templates for the stat graphs.
# The API implementation replaces '%s' with the encrypted backend id. # The API implementation replaces '%s' with the encrypted backend id.
# FIXME: For now we do not encrypt the backend id. CPU_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-bar/%s'
CPU_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-bar.png' CPU_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-ts/%s'
CPU_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-ts.png' NET_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/net-bar/%s'
NET_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/net-bar.png' NET_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/net-ts/%s'
NET_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/net-ts.png'
# Recommended refresh period for server stats # Recommended refresh period for server stats
STATS_REFRESH_PERIOD = 60 STATS_REFRESH_PERIOD = 60
......
...@@ -2,7 +2,12 @@ ...@@ -2,7 +2,12 @@
## ##
## Top-level URL for deployment. ## Top-level URL for deployment.
#STATS_BASE_URL = "https://host:port/stats" #STATS_BASE_URL = "https://host:port/stats"
#
## This key is used to decrypt the instance id / hostname in tha stats graph
## URL. It should be set to the same value that is used by Cyclades to encrypt
## the hostname (CYCLADES_STATS_SECRET_KEY).
#STATS_SECRET_KEY = "secret key"
## Image properties ## Image properties
#IMAGE_WIDTH = 210 #IMAGE_WIDTH = 210
#WIDTH = 68 #WIDTH = 68
......
...@@ -59,6 +59,7 @@ INSTALL_REQUIRES = [ ...@@ -59,6 +59,7 @@ INSTALL_REQUIRES = [
'py-rrdtool', 'py-rrdtool',
'Django>=1.4, <1.5', 'Django>=1.4, <1.5',
'snf-django-lib', 'snf-django-lib',
'pycrypto>=2.1.0',
] ]
setup( setup(
......
...@@ -43,6 +43,10 @@ from cStringIO import StringIO ...@@ -43,6 +43,10 @@ from cStringIO import StringIO
import rrdtool import rrdtool
from Crypto.Cipher import AES
from base64 import urlsafe_b64decode
from hashlib import sha256
from synnefo_stats import settings from synnefo_stats import settings
from synnefo.util.text import uenc from synnefo.util.text import uenc
...@@ -196,10 +200,8 @@ def draw_net_ts(fname, outfname): ...@@ -196,10 +200,8 @@ def draw_net_ts(fname, outfname):
outfname += "-net.png" outfname += "-net.png"
rrdtool.graph(outfname, "-s", "-1d", "-e", "-20s", rrdtool.graph(outfname, "-s", "-1d", "-e", "-20s",
#"-t", "Network traffic",
"--units", "si", "--units", "si",
"-v", "Bits/s", "-v", "Bits/s",
#"--lazy",
"COMMENT:\t\t\tAverage network traffic\\n", "COMMENT:\t\t\tAverage network traffic\\n",
"DEF:rx=%s:rx:AVERAGE" % fname, "DEF:rx=%s:rx:AVERAGE" % fname,
"DEF:tx=%s:tx:AVERAGE" % fname, "DEF:tx=%s:tx:AVERAGE" % fname,
...@@ -218,10 +220,8 @@ def draw_net_ts_w(fname, outfname): ...@@ -218,10 +220,8 @@ def draw_net_ts_w(fname, outfname):
outfname += "-net-weekly.png" outfname += "-net-weekly.png"
rrdtool.graph(outfname, "-s", "-1w", "-e", "-20s", rrdtool.graph(outfname, "-s", "-1w", "-e", "-20s",
#"-t", "Network traffic",
"--units", "si", "--units", "si",
"-v", "Bits/s", "-v", "Bits/s",
#"--lazy",
"COMMENT:\t\t\tAverage network traffic\\n", "COMMENT:\t\t\tAverage network traffic\\n",
"DEF:rx=%s:rx:AVERAGE" % fname, "DEF:rx=%s:rx:AVERAGE" % fname,
"DEF:tx=%s:tx:AVERAGE" % fname, "DEF:tx=%s:tx:AVERAGE" % fname,
...@@ -235,6 +235,14 @@ def draw_net_ts_w(fname, outfname): ...@@ -235,6 +235,14 @@ def draw_net_ts_w(fname, outfname):
return read_file(outfname) return read_file(outfname)
def decrypt(secret):
# Make sure key is 32 bytes long
key = sha256(settings.STATS_SECRET_KEY).digest()
aes = AES.new(key)
return aes.decrypt(urlsafe_b64decode(secret)).rstrip('\x00')
available_graph_types = { available_graph_types = {
'cpu-bar': draw_cpu_bar, 'cpu-bar': draw_cpu_bar,
'net-bar': draw_net_bar, 'net-bar': draw_net_bar,
...@@ -248,6 +256,7 @@ available_graph_types = { ...@@ -248,6 +256,7 @@ available_graph_types = {
@api_method(http_method='GET', token_required=False, user_required=False, @api_method(http_method='GET', token_required=False, user_required=False,
format_allowed=False, logger=log) format_allowed=False, logger=log)
def grapher(request, graph_type, hostname): def grapher(request, graph_type, hostname):
hostname = decrypt(uenc(hostname))
fname = uenc(os.path.join(settings.RRD_PREFIX, hostname)) fname = uenc(os.path.join(settings.RRD_PREFIX, hostname))
if not os.path.isdir(fname): if not os.path.isdir(fname):
raise faults.ItemNotFound('No such instance') raise faults.ItemNotFound('No such instance')
......
## -*- coding: utf-8 -*- ## -*- coding: utf-8 -*-
from django.conf import settings from django.conf import settings
STATS_SECRET_KEY = getattr(settings, 'STATS_SECRET_KEY', "secret key")
# Image properties # Image properties
IMAGE_WIDTH = getattr(settings, 'IMAGE_WIDTH', 210) IMAGE_WIDTH = getattr(settings, 'IMAGE_WIDTH', 210)
WIDTH = getattr(settings, 'WIDTH', 68) WIDTH = getattr(settings, 'WIDTH', 68)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment