Source code for atmo.keys.forms
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_ssh_public_key
from django import forms
from django.core.exceptions import ValidationError
from ..forms.mixins import AutoClassFormMixin, CreatedByModelFormMixin
from .models import SSHKey
from .utils import calculate_fingerprint
[docs]class SSHKeyForm(AutoClassFormMixin, CreatedByModelFormMixin):
"""
The form to be used when uploaded new SSH keys.
"""
prefix = 'sshkey'
key_file = forms.FileField(
label='Or select a .pub file from your computer',
help_text='This can usually be found in <code>~/.ssh/</code> on your computer.',
required=False,
widget=forms.FileInput(attrs={'accept': '.pub'}),
)
[docs] def clean_key(self):
"""
Checks if the submitted key data:
- isn't larger than 100kb
- is a valid SSH public key (e.g. dismissing if it's a private key)
- does not match any of the :attr:`valid key data prefixes
<~atmo.keys.models.SSHKey.VALID_PREFIXES>`
- already exists in the database
"""
key = self.cleaned_data['key'].strip()
if len(key) > 100000:
raise ValidationError(
'The submitted key was larger than 100kB, '
'please submit a smaller one'
)
try:
load_ssh_public_key(key.encode('utf-8'), backend=default_backend())
except ValueError:
raise ValidationError(
'The submitted key is invalid or misformatted.'
)
except UnsupportedAlgorithm:
raise ValidationError(
'The submitted key is not supported. It should start with '
'one of the following prefixes: %s.' %
', '.join(SSHKey.VALID_PREFIXES)
)
fingerprint = calculate_fingerprint(key)
if self.created_by.created_sshkeys.filter(fingerprint=fingerprint).exists():
raise ValidationError(
'There is already a SSH key with the fingerprint %s. '
'Please try a different one or use the one already uploaded.' % fingerprint,
)
return key
class Meta:
model = SSHKey
fields = ['title', 'key', 'key_file']
widgets = {
'key': forms.Textarea(
attrs={
'placeholder': 'Drag and drop a key file with the ".pub" '
'file extension here, paste the content '
'manually or use the file selector below',
}),
}