123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- from Crypto.Cipher import PKCS1_OAEP
- from Crypto.PublicKey import RSA
- from django import forms
- from django.db.models import Count
- from dcim.models import Device
- from utilities.forms import BootstrapMixin, BulkEditForm, BulkImportForm, CSVDataField, FilterChoiceField, SlugField
- from .models import Secret, SecretRole, UserKey
- def validate_rsa_key(key, is_secret=True):
- """
- Validate the format and type of an RSA key.
- """
- try:
- key = RSA.importKey(key)
- except ValueError:
- raise forms.ValidationError("Invalid RSA key. Please ensure that your key is in PEM (base64) format.")
- except Exception as e:
- raise forms.ValidationError("Invalid key detected: {}".format(e))
- if is_secret and not key.has_private():
- raise forms.ValidationError("This looks like a public key. Please provide your private RSA key.")
- elif not is_secret and key.has_private():
- raise forms.ValidationError("This looks like a private key. Please provide your public RSA key.")
- try:
- PKCS1_OAEP.new(key)
- except:
- raise forms.ValidationError("Error validating RSA key. Please ensure that your key supports PKCS#1 OAEP.")
- #
- # Secret roles
- #
- class SecretRoleForm(BootstrapMixin, forms.ModelForm):
- slug = SlugField()
- class Meta:
- model = SecretRole
- fields = ['name', 'slug']
- #
- # Secrets
- #
- class SecretForm(BootstrapMixin, forms.ModelForm):
- private_key = forms.CharField(required=False, widget=forms.HiddenInput())
- plaintext = forms.CharField(max_length=65535, required=False, label='Plaintext',
- widget=forms.PasswordInput(attrs={'class': 'requires-private-key'}))
- plaintext2 = forms.CharField(max_length=65535, required=False, label='Plaintext (verify)',
- widget=forms.PasswordInput())
- class Meta:
- model = Secret
- fields = ['role', 'name', 'plaintext', 'plaintext2']
- def clean(self):
- if self.cleaned_data['plaintext']:
- validate_rsa_key(self.cleaned_data['private_key'])
- if self.cleaned_data['plaintext'] != self.cleaned_data['plaintext2']:
- raise forms.ValidationError({
- 'plaintext2': "The two given plaintext values do not match. Please check your input."
- })
- class SecretFromCSVForm(forms.ModelForm):
- device = forms.ModelChoiceField(queryset=Device.objects.all(), required=False, to_field_name='name',
- error_messages={'invalid_choice': 'Device not found.'})
- role = forms.ModelChoiceField(queryset=SecretRole.objects.all(), to_field_name='name',
- error_messages={'invalid_choice': 'Invalid secret role.'})
- plaintext = forms.CharField()
- class Meta:
- model = Secret
- fields = ['device', 'role', 'name', 'plaintext']
- def save(self, *args, **kwargs):
- s = super(SecretFromCSVForm, self).save(*args, **kwargs)
- s.plaintext = str(self.cleaned_data['plaintext'])
- return s
- class SecretImportForm(BootstrapMixin, BulkImportForm):
- private_key = forms.CharField(widget=forms.HiddenInput())
- csv = CSVDataField(csv_form=SecretFromCSVForm, widget=forms.Textarea(attrs={'class': 'requires-private-key'}))
- class SecretBulkEditForm(BootstrapMixin, BulkEditForm):
- pk = forms.ModelMultipleChoiceField(queryset=Secret.objects.all(), widget=forms.MultipleHiddenInput)
- role = forms.ModelChoiceField(queryset=SecretRole.objects.all(), required=False)
- name = forms.CharField(max_length=100, required=False)
- class Meta:
- nullable_fields = ['name']
- class SecretFilterForm(BootstrapMixin, forms.Form):
- q = forms.CharField(required=False, label='Search')
- role = FilterChoiceField(queryset=SecretRole.objects.annotate(filter_count=Count('secrets')), to_field_name='slug')
- #
- # UserKeys
- #
- class UserKeyForm(BootstrapMixin, forms.ModelForm):
- class Meta:
- model = UserKey
- fields = ['public_key']
- help_texts = {
- 'public_key': "Enter your public RSA key. Keep the private one with you; you'll need it for decryption.",
- }
- def clean_public_key(self):
- key = self.cleaned_data['public_key']
- # Validate the RSA key format.
- validate_rsa_key(key, is_secret=False)
- return key
- class ActivateUserKeyForm(forms.Form):
- _selected_action = forms.ModelMultipleChoiceField(queryset=UserKey.objects.all(), label='User Keys')
- secret_key = forms.CharField(label='Your private key', widget=forms.Textarea(attrs={'class': 'vLargeTextField'}))
|