~ubuntu-branches/ubuntu/raring/maas/raring-updates

« back to all changes in this revision

Viewing changes to src/maasserver/models/sshkey.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2012-07-03 17:42:37 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20120703174237-p8l0keuuznfg721k
Tags: 0.1+bzr709+dfsg-0ubuntu1
* New Upstream release
* debian/control:
  - Depends on python-celery, python-tempita, libjs-yui3-{full,min},
    libjs-raphael
* debian/maas.install:
  - Install apiclient, celeryconfig.py, maas-import-pxe-files, preseeds_v2.
  - Update to install various files from chroot, rather tha manually copy
    them from the source.
* debian/maas.links: symlink celeryconfig.py
* debian/maas.maas-celery.upstart: Add job.
* debian/rules:
  - Install celery upstart job.
  - Do not install jslibs as packages are now used.
  - Drop copying of maas_local_settings_sample.py as source now ships
    a maas_local_settings.py
* debian/patches:
  - 04-maas-http-fix.patch: Drop. Merged upstream.
  - 01-fix-database-settings.patch: Refreshed.
  - 99_enums_js.patch: Added until creation of enum.js / build process
    is fixed.
* debian/maas.postinst: Update bzr version to correctly handle upgrades.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2012 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
""":class:`SSHKey` and friends."""
 
5
 
 
6
from __future__ import (
 
7
    absolute_import,
 
8
    print_function,
 
9
    unicode_literals,
 
10
    )
 
11
 
 
12
__metaclass__ = type
 
13
__all__ = [
 
14
    'SSHKey',
 
15
    ]
 
16
 
 
17
 
 
18
import binascii
 
19
from cgi import escape
 
20
 
 
21
from django.contrib.auth.models import User
 
22
from django.core.exceptions import ValidationError
 
23
from django.db.models import (
 
24
    ForeignKey,
 
25
    Manager,
 
26
    TextField,
 
27
    )
 
28
from django.utils.safestring import mark_safe
 
29
from maasserver import DefaultMeta
 
30
from maasserver.models.cleansave import CleanSave
 
31
from maasserver.models.timestampedmodel import TimestampedModel
 
32
from twisted.conch.ssh.keys import (
 
33
    BadKeyError,
 
34
    Key,
 
35
    )
 
36
 
 
37
 
 
38
class SSHKeyManager(Manager):
 
39
    """A utility to manage the colletion of `SSHKey`s."""
 
40
 
 
41
    def get_keys_for_user(self, user):
 
42
        """Return the text of the ssh keys associated with a user."""
 
43
        return SSHKey.objects.filter(user=user).values_list('key', flat=True)
 
44
 
 
45
 
 
46
def validate_ssh_public_key(value):
 
47
    """Validate that the given value contains a valid SSH public key."""
 
48
    try:
 
49
        key = Key.fromString(value)
 
50
        if not key.isPublic():
 
51
            raise ValidationError(
 
52
                "Invalid SSH public key (this key is a private key).")
 
53
    except (BadKeyError, binascii.Error):
 
54
        raise ValidationError("Invalid SSH public key.")
 
55
 
 
56
 
 
57
HELLIPSIS = '…'
 
58
 
 
59
 
 
60
def get_html_display_for_key(key, size):
 
61
    """Return a compact HTML representation of this key with a boundary on
 
62
    the size of the resulting string.
 
63
 
 
64
    A key typically looks like this: 'key_type key_string comment'.
 
65
    What we want here is display the key_type and, if possible (i.e. if it
 
66
    fits in the boundary that `size` gives us), the comment.  If possible we
 
67
    also want to display a truncated key_string.  If the comment is too big
 
68
    to fit in, we simply display a cropped version of the whole string.
 
69
 
 
70
    :param key: The key for which we want an HTML representation.
 
71
    :type name: basestring
 
72
    :param size: The maximum size of the representation.  This may not be
 
73
        met exactly.
 
74
    :type size: int
 
75
    :return: The HTML representation of this key.
 
76
    :rtype: basestring
 
77
    """
 
78
    key = key.strip()
 
79
    key_parts = key.split(' ', 2)
 
80
 
 
81
    if len(key_parts) == 3:
 
82
        key_type = key_parts[0]
 
83
        key_string = key_parts[1]
 
84
        comment = key_parts[2]
 
85
        room_for_key = (
 
86
            size - (len(key_type) + len(comment) + len(HELLIPSIS) + 2))
 
87
        if room_for_key > 0:
 
88
            return '%s %.*s%s %s' % (
 
89
                escape(key_type, quote=True),
 
90
                room_for_key,
 
91
                escape(key_string, quote=True),
 
92
                HELLIPSIS,
 
93
                escape(comment, quote=True))
 
94
 
 
95
    if len(key) > size:
 
96
        return '%.*s%s' % (
 
97
            size - len(HELLIPSIS),
 
98
            escape(key, quote=True),
 
99
            HELLIPSIS)
 
100
    else:
 
101
        return escape(key, quote=True)
 
102
 
 
103
 
 
104
MAX_KEY_DISPLAY = 50
 
105
 
 
106
 
 
107
class SSHKey(CleanSave, TimestampedModel):
 
108
    """A `SSHKey` represents a user public SSH key.
 
109
 
 
110
    Users will be able to access `Node`s using any of their registered keys.
 
111
 
 
112
    :ivar user: The user which owns the key.
 
113
    :ivar key: The ssh public key.
 
114
    """
 
115
 
 
116
    objects = SSHKeyManager()
 
117
 
 
118
    user = ForeignKey(User, null=False, editable=False)
 
119
 
 
120
    key = TextField(
 
121
        null=False, editable=True, validators=[validate_ssh_public_key])
 
122
 
 
123
    class Meta(DefaultMeta):
 
124
        verbose_name = "SSH key"
 
125
        unique_together = ('user', 'key')
 
126
 
 
127
    def unique_error_message(self, model_class, unique_check):
 
128
        if unique_check == ('user', 'key'):
 
129
                return "This key has already been added for this user."
 
130
        return super(
 
131
            SSHKey, self).unique_error_message(model_class, unique_check)
 
132
 
 
133
    def __unicode__(self):
 
134
        return self.key
 
135
 
 
136
    def display_html(self):
 
137
        """Return a compact HTML representation of this key.
 
138
 
 
139
        :return: The HTML representation of this key.
 
140
        :rtype: basestring
 
141
        """
 
142
        return mark_safe(get_html_display_for_key(self.key, MAX_KEY_DISPLAY))