mirror of
https://github.com/ansible/awx.git
synced 2026-03-18 17:37:30 -02:30
migrate existing survey passwords to be encrypted
see: https://github.com/ansible/ansible-tower/issues/7046
This commit is contained in:
committed by
Matthew Jones
parent
4be4e3db7f
commit
f26bdb3e96
17
awx/main/migrations/0011_v322_encrypt_survey_passwords.py
Normal file
17
awx/main/migrations/0011_v322_encrypt_survey_passwords.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
from awx.main.migrations import ActivityStreamDisabledMigration
|
||||||
|
from awx.main.migrations import _reencrypt as reencrypt
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(ActivityStreamDisabledMigration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0010_v322_add_support_for_ovirt4_inventory'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(reencrypt.encrypt_survey_passwords),
|
||||||
|
]
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
import six
|
||||||
|
|
||||||
from awx.conf.migrations._reencrypt import (
|
from awx.conf.migrations._reencrypt import (
|
||||||
decrypt_field,
|
decrypt_field,
|
||||||
@@ -72,3 +74,38 @@ def _unified_jobs(apps):
|
|||||||
uj.start_args = decrypt_field(uj, 'start_args')
|
uj.start_args = decrypt_field(uj, 'start_args')
|
||||||
uj.start_args = encrypt_field(uj, 'start_args')
|
uj.start_args = encrypt_field(uj, 'start_args')
|
||||||
uj.save()
|
uj.save()
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_survey_passwords(apps, schema_editor):
|
||||||
|
_encrypt_survey_passwords(
|
||||||
|
apps.get_model('main', 'Job'),
|
||||||
|
apps.get_model('main', 'JobTemplate'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _encrypt_survey_passwords(Job, JobTemplate):
|
||||||
|
from awx.main.utils.encryption import encrypt_value
|
||||||
|
for jt in JobTemplate.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', ''):
|
||||||
|
if field['default'].startswith('$encrypted$'):
|
||||||
|
continue
|
||||||
|
field['default'] = encrypt_value(field['default'], pk=None)
|
||||||
|
changed = True
|
||||||
|
if changed:
|
||||||
|
jt.save()
|
||||||
|
|
||||||
|
for job in Job.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()
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ from django.apps import apps
|
|||||||
|
|
||||||
from awx.main.models import (
|
from awx.main.models import (
|
||||||
UnifiedJob,
|
UnifiedJob,
|
||||||
|
Job,
|
||||||
|
JobTemplate,
|
||||||
NotificationTemplate,
|
NotificationTemplate,
|
||||||
Credential,
|
Credential,
|
||||||
)
|
)
|
||||||
@@ -20,9 +22,10 @@ from awx.main.migrations._reencrypt import (
|
|||||||
_notification_templates,
|
_notification_templates,
|
||||||
_credentials,
|
_credentials,
|
||||||
_unified_jobs,
|
_unified_jobs,
|
||||||
|
_encrypt_survey_passwords
|
||||||
)
|
)
|
||||||
|
|
||||||
from awx.main.utils import decrypt_field
|
from awx.main.utils import decrypt_field, get_encryption_key, decrypt_value
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -93,3 +96,54 @@ def test_unified_job_migration(old_enc, new_enc, value):
|
|||||||
# Exception if the encryption type of AESCBC is not properly skipped, ensures
|
# Exception if the encryption type of AESCBC is not properly skipped, ensures
|
||||||
# our `startswith` calls don't have typos
|
# our `startswith` calls don't have typos
|
||||||
_unified_jobs(apps)
|
_unified_jobs(apps)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_survey_default_password_encryption(job_template_factory):
|
||||||
|
jt = job_template_factory('jt', organization='org1', project='prj',
|
||||||
|
inventory='inv', credential='cred').job_template
|
||||||
|
jt.survey_enabled = True
|
||||||
|
jt.survey_spec = {
|
||||||
|
'description': 'A survey',
|
||||||
|
'spec': [{
|
||||||
|
'index': 0,
|
||||||
|
'question_name': 'What is your password?',
|
||||||
|
'required': True,
|
||||||
|
'variable': 'secret_value',
|
||||||
|
'default': 'SUPERSECRET',
|
||||||
|
'type': 'password'
|
||||||
|
}],
|
||||||
|
'name': 'my survey'
|
||||||
|
}
|
||||||
|
jt.save()
|
||||||
|
|
||||||
|
_encrypt_survey_passwords(Job, JobTemplate)
|
||||||
|
spec = JobTemplate.objects.get(pk=jt.pk).survey_spec['spec']
|
||||||
|
assert decrypt_value(get_encryption_key('value', pk=None), spec[0]['default']) == 'SUPERSECRET'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_job_survey_vars_encryption(job_template_factory):
|
||||||
|
jt = job_template_factory('jt', organization='org1', project='prj',
|
||||||
|
inventory='inv', credential='cred').job_template
|
||||||
|
jt.survey_enabled = True
|
||||||
|
jt.survey_spec = {
|
||||||
|
'description': 'A survey',
|
||||||
|
'spec': [{
|
||||||
|
'index': 0,
|
||||||
|
'question_name': 'What is your password?',
|
||||||
|
'required': True,
|
||||||
|
'variable': 'secret_value',
|
||||||
|
'default': '',
|
||||||
|
'type': 'password'
|
||||||
|
}],
|
||||||
|
'name': 'my survey'
|
||||||
|
}
|
||||||
|
jt.save()
|
||||||
|
job = jt.create_unified_job()
|
||||||
|
job.extra_vars = json.dumps({'secret_value': 'SUPERSECRET'})
|
||||||
|
job.save()
|
||||||
|
|
||||||
|
_encrypt_survey_passwords(Job, JobTemplate)
|
||||||
|
job = Job.objects.get(pk=job.pk)
|
||||||
|
assert json.loads(job.decrypted_extra_vars()) == {'secret_value': 'SUPERSECRET'}
|
||||||
|
|||||||
Reference in New Issue
Block a user