def test_survey_spec(self, inventory, project, survey_spec_factory, cls): params = {} if cls == 'JobTemplate': params['inventory'] = inventory params['project'] = project # test basic decryption jt = getattr(models, cls).objects.create( name='Example Template', survey_spec=survey_spec_factory([{ 'variable': 'secret_key', 'default': encrypt_value('donttell', pk=None), 'type': 'password' }]), survey_enabled=True, **params ) job = jt.create_unified_job() assert jt.survey_spec['spec'][0]['default'].startswith(PREFIX) assert job.survey_passwords == {'secret_key': '$encrypted$'} assert json.loads(job.decrypted_extra_vars())['secret_key'] == 'donttell' # re-key the extra_vars new_key = regenerate_secret_key.Command().handle() new_job = models.UnifiedJob.objects.get(pk=job.pk) assert new_job.extra_vars != job.extra_vars # verify that the old SECRET_KEY doesn't work with pytest.raises(InvalidToken): new_job.decrypted_extra_vars() # verify that the new SECRET_KEY *does* work with override_settings(SECRET_KEY=new_key): assert json.loads( new_job.decrypted_extra_vars() )['secret_key'] == 'donttell'
def _oauth2_app_secrets(self): for app in OAuth2Application.objects.iterator(): raw = app.client_secret app.client_secret = raw encrypted = encrypt_value(raw, secret_key=self.new_key) OAuth2Application.objects.filter(pk=app.pk).update( client_secret=encrypted)
def _encrypt_survey_passwords(Job, JobTemplate, WorkflowJob, WorkflowJobTemplate): from awx.main.utils.encryption import encrypt_value for _type in (JobTemplate, WorkflowJobTemplate): for jt in _type.objects.exclude(survey_spec={}): changed = False if jt.survey_spec.get('spec', []): for field in jt.survey_spec['spec']: if field.get('type') == 'password' and field.get( 'default', ''): default = field['default'] if default.startswith('$encrypted$'): if default == '$encrypted$': # If you have a survey_spec with a literal # '$encrypted$' as the default, you have # encountered a known bug in awx/Tower # https://github.com/ansible/ansible-tower/issues/7800 logger.error( '{}.pk={} survey_spec has ambiguous $encrypted$ default for {}, needs attention...' .format(jt, jt.pk, field['variable'])) field['default'] = '' changed = True continue field['default'] = encrypt_value(field['default'], pk=None) changed = True if changed: jt.save() for _type in (Job, WorkflowJob): for job in _type.objects.defer('result_stdout_text').exclude( survey_passwords={}).iterator(): changed = False for key in job.survey_passwords: if key in job.extra_vars: extra_vars = json.loads(job.extra_vars) if not extra_vars.get( key, '') or extra_vars[key].startswith('$encrypted$'): continue extra_vars[key] = encrypt_value(extra_vars[key], pk=None) job.extra_vars = json.dumps(extra_vars) changed = True if changed: job.save()
def _survey_passwords(self): for _type in (JobTemplate, WorkflowJobTemplate): for jt in _type.objects.exclude(survey_spec={}): changed = False if jt.survey_spec.get('spec', []): for field in jt.survey_spec['spec']: if field.get('type') == 'password' and field.get( 'default', ''): raw = decrypt_value( get_encryption_key('value', None, secret_key=self.old_key), field['default']) field['default'] = encrypt_value( raw, pk=None, secret_key=self.new_key) changed = True if changed: jt.save(update_fields=["survey_spec"]) for _type in (Job, WorkflowJob): for job in _type.objects.exclude(survey_passwords={}).iterator(): changed = False for key in job.survey_passwords: if key in job.extra_vars: extra_vars = json.loads(job.extra_vars) if not extra_vars.get(key): continue raw = decrypt_value( get_encryption_key('value', None, secret_key=self.old_key), extra_vars[key]) extra_vars[key] = encrypt_value( raw, pk=None, secret_key=self.new_key) job.extra_vars = json.dumps(extra_vars) changed = True if changed: job.save(update_fields=["extra_vars"])
import tempfile import json import yaml import pytest from awx.main.utils.encryption import encrypt_value from awx.main.tasks import RunJob from awx.main.models import ( Job, JobTemplate, JobLaunchConfig, WorkflowJobTemplate ) from awx.main.utils.safe_yaml import SafeLoader ENCRYPTED_SECRET = encrypt_value('secret') @pytest.mark.survey class SurveyVariableValidation: def test_survey_answers_as_string(self, job_template_factory): objects = job_template_factory( 'job-template-with-survey', survey=[{'variable': 'var1', 'type': 'text'}], persisted=False) jt = objects.job_template user_extra_vars = json.dumps({'var1': 'asdf'}) accepted, ignored, errors = jt._accept_or_ignore_job_kwargs(extra_vars=user_extra_vars) assert ignored.get('extra_vars', {}) == {}, [str(element) for element in errors] assert 'var1' in accepted['extra_vars']
def get_db_prep_value(self, value, connection, prepared=False): return super(OAuth2ClientSecretField, self).get_db_prep_value(encrypt_value(value), connection, prepared)
def test_encrypt_empty_string_twice(self): # Encryption is idempotent val = encryption.encrypt_value('foobar') val2 = encryption.encrypt_value(val) assert encryption.decrypt_value(self._key, val2) == 'foobar'
def test_encrypt_encryption_key(self): assert encryption.encrypt_value('$encrypted$') == '$encrypted$'
def test_encrypt_empty_string(self): assert encryption.encrypt_value('') == ''