| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- from Crypto.Cipher import PKCS1_OAEP
- from Crypto.PublicKey import RSA
- from django import forms
- from taggit.forms import TagField
- from dcim.models import Device
- from extras.forms import (
- AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelForm, CustomFieldModelCSVForm,
- )
- from utilities.forms import (
- APISelect, APISelectMultiple, BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
- FlexibleModelChoiceField, SlugField, StaticSelect2Multiple, TagFilterField,
- )
- from .constants import *
- from .models import Secret, SecretRole, UserKey
- def validate_rsa_key(key, is_secret=True):
- """
- Validate the format and type of an RSA key.
- """
- if key.startswith('ssh-rsa '):
- raise forms.ValidationError("OpenSSH line format is not supported. Please ensure that your public is in PEM (base64) format.")
- 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 Exception:
- 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', 'description', 'users', 'groups',
- ]
- widgets = {
- 'users': StaticSelect2Multiple(),
- 'groups': StaticSelect2Multiple(),
- }
- class SecretRoleCSVForm(forms.ModelForm):
- slug = SlugField()
- class Meta:
- model = SecretRole
- fields = SecretRole.csv_headers
- help_texts = {
- 'name': 'Name of secret role',
- }
- #
- # Secrets
- #
- class SecretForm(BootstrapMixin, CustomFieldModelForm):
- plaintext = forms.CharField(
- max_length=SECRET_PLAINTEXT_MAX_LENGTH,
- required=False,
- label='Plaintext',
- widget=forms.PasswordInput(
- attrs={
- 'class': 'requires-session-key',
- }
- )
- )
- plaintext2 = forms.CharField(
- max_length=SECRET_PLAINTEXT_MAX_LENGTH,
- required=False,
- label='Plaintext (verify)',
- widget=forms.PasswordInput()
- )
- role = DynamicModelChoiceField(
- queryset=SecretRole.objects.all(),
- widget=APISelect(
- api_url="/api/secrets/secret-roles/"
- )
- )
- tags = TagField(
- required=False
- )
- class Meta:
- model = Secret
- fields = [
- 'role', 'name', 'plaintext', 'plaintext2', 'tags',
- ]
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- # A plaintext value is required when creating a new Secret
- if not self.instance.pk:
- self.fields['plaintext'].required = True
- def clean(self):
- # Verify that the provided plaintext values match
- 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 SecretCSVForm(CustomFieldModelCSVForm):
- device = FlexibleModelChoiceField(
- queryset=Device.objects.all(),
- to_field_name='name',
- help_text='Device name or ID',
- error_messages={
- 'invalid_choice': 'Device not found.',
- }
- )
- role = forms.ModelChoiceField(
- queryset=SecretRole.objects.all(),
- to_field_name='name',
- help_text='Name of assigned role',
- error_messages={
- 'invalid_choice': 'Invalid secret role.',
- }
- )
- plaintext = forms.CharField(
- help_text='Plaintext secret data'
- )
- class Meta:
- model = Secret
- fields = Secret.csv_headers
- help_texts = {
- 'name': 'Name or username',
- }
- def save(self, *args, **kwargs):
- s = super().save(*args, **kwargs)
- s.plaintext = str(self.cleaned_data['plaintext'])
- return s
- class SecretBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
- pk = forms.ModelMultipleChoiceField(
- queryset=Secret.objects.all(),
- widget=forms.MultipleHiddenInput()
- )
- role = DynamicModelChoiceField(
- queryset=SecretRole.objects.all(),
- required=False,
- widget=APISelect(
- api_url="/api/secrets/secret-roles/"
- )
- )
- name = forms.CharField(
- max_length=100,
- required=False
- )
- class Meta:
- nullable_fields = [
- 'name',
- ]
- class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm):
- model = Secret
- q = forms.CharField(
- required=False,
- label='Search'
- )
- role = DynamicModelMultipleChoiceField(
- queryset=SecretRole.objects.all(),
- to_field_name='slug',
- required=True,
- widget=APISelectMultiple(
- api_url="/api/secrets/secret-roles/",
- value_field="slug",
- )
- )
- tag = TagFilterField(model)
- #
- # 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. "
- "Please note that passphrase-protected keys are not supported.",
- }
- labels = {
- 'public_key': ''
- }
- 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(
- widget=forms.Textarea(
- attrs={
- 'class': 'vLargeTextField',
- }
- ),
- label='Your private key'
- )
|