1
# Copyright 2014 Cloudbase Solutions SRL.
2
# Copyright 2012 Canonical Ltd. This software is licensed under the
3
# GNU Affero General Public License version 3 (see the file LICENSE).
5
""":class:`SSLKey` and friends."""
7
from __future__ import (
21
from cgi import escape
23
from django.contrib.auth.models import User
24
from django.core.exceptions import ValidationError
25
from django.db.models import (
30
from django.utils.safestring import mark_safe
31
from maasserver import (
35
from maasserver.models.cleansave import CleanSave
36
from maasserver.models.timestampedmodel import TimestampedModel
37
from OpenSSL import crypto
40
class SSLKeyManager(Manager):
41
"""A utility to manage the colletion of `SSLKey`s."""
43
def get_keys_for_user(self, user):
44
"""Return the text of the ssl keys associated with a user."""
45
return SSLKey.objects.filter(user=user).values_list('key', flat=True)
48
def validate_ssl_key(value):
49
"""Validate that the given value contains a valid SSL key."""
51
crypto.load_certificate(crypto.FILETYPE_PEM, value)
53
# crypto.load_certificate raises all sorts of exceptions.
54
# Here, we catch them all and return a ValidationError since this
55
# method only aims at validating keys and not return the exact cause of
57
logger.exception("Invalid SSL key.")
58
raise ValidationError("Invalid SSL key.")
61
def find_ssl_common_name(subject):
62
"""Returns the common name for the ssl key."""
63
for component in subject.get_components():
64
if len(component) < 2:
66
if component[0] == 'CN':
71
def get_html_display_for_key(key):
72
"""Returns the html escaped string for the key."""
73
cert = crypto.load_certificate(crypto.FILETYPE_PEM, key)
74
subject = cert.get_subject()
75
md5 = cert.digest('MD5')
76
cn = find_ssl_common_name(subject)
78
key = "%s %s" % (cn, md5)
81
return escape(key, quote=True)
84
class SSLKey(CleanSave, TimestampedModel):
85
"""An `SSLKey` represents a user SSL key.
87
Users will be able to access Windows winrm service with
88
any of the registered keys.
90
:ivar user: The user which owns the key.
91
:ivar key: The SSL key.
94
objects = SSLKeyManager()
96
user = ForeignKey(User, null=False, editable=False)
98
null=False, blank=False, editable=True, validators=[validate_ssl_key])
100
class Meta(DefaultMeta):
101
verbose_name = "SSL key"
102
unique_together = ('user', 'key')
104
def unique_error_message(self, model_class, unique_check):
105
if unique_check == ('user', 'key'):
106
return "This key has already been added for this user."
108
SSLKey, self).unique_error_message(model_class, unique_check)
110
def __unicode__(self):
113
def display_html(self):
114
"""Return a compact HTML representation of this key.
116
:return: The HTML representation of this key.
119
return mark_safe(get_html_display_for_key(self.key))