diff --git a/awx/main/tests/unit/test_validators.py b/awx/main/tests/unit/test_validators.py index 3500f8d023..2221f241da 100644 --- a/awx/main/tests/unit/test_validators.py +++ b/awx/main/tests/unit/test_validators.py @@ -19,6 +19,24 @@ from rest_framework.serializers import ValidationError as RestValidationError import pytest +def test_invalid_keys(): + invalid_keys = [ + "---BEGIN FOO -----foobar-----END FOO----", + "-----BEGIN FOO---foobar-----END FOO----", + "-----BEGIN FOO-----foobar---END FOO----", + "----- BEGIN FOO ----- foobar ----- FAIL FOO ----", + "----- FAIL FOO ----- foobar ----- END FOO ----", + "----BEGIN FOO----foobar----END FOO--------BEGIN FOO----foobar----END FOO----" + ] + for invalid_key in invalid_keys: + with pytest.raises(ValidationError): + validate_private_key(invalid_key) + with pytest.raises(ValidationError): + validate_certificate(invalid_key) + with pytest.raises(ValidationError): + validate_ssh_private_key(invalid_key) + + def test_valid_catted_rsa_key(): valid_key = TEST_CATTED_SSH_KEY_DATA pem_objects = validate_private_key(valid_key) @@ -55,16 +73,6 @@ def test_valid_locked_rsa_key(): assert pem_objects[0]['key_enc'] -def test_invalid_rsa_key(): - invalid_key = TEST_SSH_KEY_DATA.replace('-----END', '----END') - with pytest.raises(ValidationError): - validate_private_key(invalid_key) - with pytest.raises(ValidationError): - validate_certificate(invalid_key) - with pytest.raises(ValidationError): - validate_ssh_private_key(invalid_key) - - def test_valid_openssh_key(): valid_key = TEST_OPENSSH_KEY_DATA pem_objects = validate_private_key(valid_key) diff --git a/awx/main/validators.py b/awx/main/validators.py index 0c6a9dc569..3975e6f053 100644 --- a/awx/main/validators.py +++ b/awx/main/validators.py @@ -48,11 +48,10 @@ def validate_pem(data, min_keys=0, max_keys=None, min_certs=0, max_certs=None): # Build regular expressions for matching each object in the PEM file. pem_obj_re = re.compile( - r'^-{5}\ *BEGIN ([A-Z ]+?)\ *-{5}' + - r'\s*(.+?)\s*' + - r'-{5}\ *END [A-Z ]+?\ *-{5}' + - r'\s?(.*?)$', - re.DOTALL + r'^-{4,} *BEGIN (?P[A-Z ]+?) *-{4,}' + + r'\s*(?P.+?)\s*' + + r'-{4,} *END [A-Z ]+? *-{4,}' + + r'(?P.*?)$', re.DOTALL ) pem_obj_header_re = re.compile(r'^(.+?):\s*?(.+?)(\\??)$') @@ -68,12 +67,13 @@ def validate_pem(data, min_keys=0, max_keys=None, min_certs=0, max_certs=None): raise ValidationError(_('Invalid certificate or key: %s...') % data[:100]) # The rest of the PEM data to process - data = match.group(3).lstrip() + data = match.group('next').lstrip() + print data # Check PEM object type, check key type if private key. pem_obj_info = {} pem_obj_info['all'] = match.group(0) - pem_obj_info['type'] = pem_obj_type = match.group(1) + pem_obj_info['type'] = pem_obj_type = match.group('type') if pem_obj_type.endswith('PRIVATE KEY'): key_count += 1 pem_obj_info['type'] = 'PRIVATE KEY' @@ -88,7 +88,7 @@ def validate_pem(data, min_keys=0, max_keys=None, min_certs=0, max_certs=None): raise ValidationError(_('Unsupported PEM object type: "%s"') % pem_obj_type) # Ensure that this PEM object is valid base64 data. - pem_obj_info['data'] = match.group(2) + pem_obj_info['data'] = match.group('data') base64_data = '' line_continues = False for line in pem_obj_info['data'].splitlines(): @@ -169,8 +169,10 @@ def validate_certificate(data): Validate that data contains one or more certificates. Adds BEGIN/END lines if necessary. """ - if 'BEGIN CERTIFICATE' not in data: - data = '-----BEGIN CERTIFICATE-----\n{}\n-----END CERTIFICATE-----\n'.format(data) + if 'BEGIN' not in data: + data = "-----BEGIN CERTIFICATE-----\n{}".format(data) + if 'END' not in data: + data = "{}\n-----END CERTIFICATE-----\n".format(data) return validate_pem(data, max_keys=0, min_certs=1)