Пример #1
0
def test_clean_credential_with_ssh_type(credentialtype_ssh, job_template):
    credential = Credential(name='My Credential',
                            credential_type=credentialtype_ssh)
    credential.save()

    job_template.credential = credential
    job_template.full_clean()
def test_prevent_multiple_machine_creds_at_launch(get, post, job_template, admin, machine_credential):
    other_cred = Credential(credential_type=machine_credential.credential_type, name="Second", inputs={'username': '******'})
    other_cred.save()
    creds = [machine_credential.pk, other_cred.pk]
    url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk})
    resp = post(url, {'credentials': creds}, admin)
    assert 'Cannot assign multiple Machine credentials.' in smart_str(resp.content)
Пример #3
0
def test_field_removal(put, organization, admin, credentialtype_ssh):
    params = {
        'name': 'Best credential ever',
        'credential_type': 1,
        'inputs': {
            'username': '******',
            'password': '',
        }
    }
    cred = Credential(credential_type=credentialtype_ssh,
                      name='Best credential ever',
                      organization=organization,
                      inputs={
                          'username': u'jim',
                          'password': u'secret'
                      })
    cred.save()

    params['organization'] = organization.id
    response = put(reverse('api:credential_detail', kwargs={'pk': cred.pk}),
                   params, admin)
    assert response.status_code == 200

    cred = Credential.objects.all()[:1].get()
    assert cred.inputs['username'] == 'joe'
    assert 'password' not in cred.inputs
Пример #4
0
def test_ssh_bad_key_unlock_not_checked(put, organization, admin,
                                        credentialtype_ssh):
    params = {
        'name': 'Best credential ever',
        'credential_type': 1,
        'inputs': {
            'username': '******',
            'ssh_key_data': 'invalid-key',
            'ssh_key_unlock': 'unchecked-unlock',
        }
    }
    cred = Credential(credential_type=credentialtype_ssh,
                      name='Best credential ever',
                      organization=organization,
                      inputs={
                          'username': u'oscar',
                          'ssh_key_data': 'invalid-key',
                          'ssh_key_unlock': 'unchecked-unlock',
                      })
    cred.save()

    params['organization'] = organization.id
    response = put(reverse('api:credential_detail', kwargs={'pk': cred.pk}),
                   params, admin)
    assert response.status_code == 400
    assert response.data['inputs']['ssh_key_data'] == [
        'Invalid certificate or key: invalid-key...'
    ]
    assert 'ssh_key_unlock' not in response.data['inputs']
Пример #5
0
def test_secret_encryption_previous_value(patch, organization, admin,
                                          credentialtype_ssh):
    params = {
        'inputs': {
            'username': '******',
            'password': '******',
        }
    }
    cred = Credential(credential_type=credentialtype_ssh,
                      name='Best credential ever',
                      organization=organization,
                      inputs={
                          'username': u'jim',
                          'password': u'secret'
                      })
    cred.save()

    assert decrypt_field(cred, 'password') == 'secret'
    response = patch(reverse('api:credential_detail', kwargs={'pk': cred.pk}),
                     params, admin)
    assert response.status_code == 200

    cred = Credential.objects.all()[:1].get()
    assert cred.inputs['username'] == 'joe'
    assert cred.inputs['password'].startswith('$encrypted$UTF8$AES')
    assert decrypt_field(cred, 'password') == 'secret'
Пример #6
0
def job_template_with_ids(job_template_factory):
    # Create non-persisted objects with IDs to send to job_template_factory
    ssh_type = CredentialType(kind='ssh')
    credential = Credential(id=1,
                            pk=1,
                            name='testcred',
                            credential_type=ssh_type)

    net_type = CredentialType(kind='net')
    net_cred = Credential(id=2,
                          pk=2,
                          name='testnetcred',
                          credential_type=net_type)

    cloud_type = CredentialType(kind='aws')
    cloud_cred = Credential(id=3,
                            pk=3,
                            name='testcloudcred',
                            credential_type=cloud_type)

    inv = Inventory(id=11, pk=11, name='testinv')
    proj = Project(id=14, pk=14, name='testproj')

    jt_objects = job_template_factory('testJT',
                                      project=proj,
                                      inventory=inv,
                                      credential=credential,
                                      cloud_credential=cloud_cred,
                                      network_credential=net_cred,
                                      persisted=False)
    jt = jt_objects.job_template
    jt.organization = Organization(id=1, pk=1, name='fooOrg')
    return jt
Пример #7
0
def test_ssh_unlock_with_prior_value(put, organization, admin,
                                     credentialtype_ssh):
    params = {
        'name': 'Best credential ever',
        'credential_type': 1,
        'inputs': {
            'username': '******',
            'ssh_key_data': '$encrypted$',
            'ssh_key_unlock': 'new-unlock',
        }
    }
    cred = Credential(credential_type=credentialtype_ssh,
                      name='Best credential ever',
                      organization=organization,
                      inputs={
                          'username': u'joe',
                          'ssh_key_data': EXAMPLE_ENCRYPTED_PRIVATE_KEY,
                          'ssh_key_unlock': 'old-unlock'
                      })
    cred.save()

    params['organization'] = organization.id
    response = put(reverse('api:credential_detail', kwargs={'pk': cred.pk}),
                   params, admin)
    assert response.status_code == 200

    cred = Credential.objects.all()[:1].get()
    assert decrypt_field(cred, 'ssh_key_unlock') == 'new-unlock'
Пример #8
0
def test_ssh_unlock_not_needed(put, organization, admin, credentialtype_ssh):
    params = {
        'name': 'Best credential ever',
        'credential_type': 1,
        'inputs': {
            'username': '******',
            'ssh_key_data': '$encrypted$',
            'ssh_key_unlock': 'superfluous-key-unlock',
        }
    }
    cred = Credential(credential_type=credentialtype_ssh,
                      name='Best credential ever',
                      organization=organization,
                      inputs={
                          'username': u'joe',
                          'ssh_key_data': EXAMPLE_PRIVATE_KEY,
                      })
    cred.save()

    params['organization'] = organization.id
    response = put(reverse('api:credential_detail', kwargs={'pk': cred.pk}),
                   params, admin)
    assert response.status_code == 400
    assert response.data['inputs']['ssh_key_unlock'] == [
        'should not be set when SSH key is not encrypted.'
    ]
Пример #9
0
    def handle(self, *args, **kwargs):
        changed = False

        # Create a default organization as the first superuser found.
        try:
            superuser = User.objects.filter(is_superuser=True).order_by('pk')[0]
        except IndexError:
            superuser = None
        with impersonate(superuser):
            with disable_computed_fields():
                if not Organization.objects.exists():
                    o = Organization.objects.create(name='Default')

                    p = Project(
                        name='Demo Project',
                        scm_type='git',
                        scm_url='https://github.com/ansible/ansible-tower-samples',
                        scm_update_on_launch=True,
                        scm_update_cache_timeout=0,
                        organization=o,
                    )
                    p.save(skip_update=True)

                    ssh_type = CredentialType.objects.filter(namespace='ssh').first()
                    c = Credential.objects.create(
                        credential_type=ssh_type, name='Demo Credential', inputs={'username': superuser.username}, created_by=superuser
                    )

                    c.admin_role.members.add(superuser)

                    public_galaxy_credential = Credential(
                        name='Ansible Galaxy',
                        managed_by_tower=True,
                        credential_type=CredentialType.objects.get(kind='galaxy'),
                        inputs={'url': 'https://galaxy.ansible.com/'},
                    )
                    public_galaxy_credential.save()
                    o.galaxy_credentials.add(public_galaxy_credential)

                    i = Inventory.objects.create(name='Demo Inventory', organization=o, created_by=superuser)

                    Host.objects.create(
                        name='localhost',
                        inventory=i,
                        variables="ansible_connection: local\nansible_python_interpreter: '{{ ansible_playbook_python }}'",
                        created_by=superuser,
                    )

                    jt = JobTemplate.objects.create(name='Demo Job Template', playbook='hello_world.yml', project=p, inventory=i)
                    jt.credentials.add(c)

                    print('Default organization added.')
                    print('Demo Credential, Inventory, and Job Template added.')
                    changed = True

        if changed:
            print('(changed: True)')
        else:
            print('(changed: False)')
def test_unique_hash_with_unicode():
    ct = CredentialType(name=u'Väult', kind='vault')
    cred = Credential(id=4,
                      name=u'Iñtërnâtiônàlizætiøn',
                      credential_type=ct,
                      inputs={u'vault_id': u'🐉🐉🐉'},
                      credential_type_id=42)
    assert cred.unique_hash(display=True) == u'Väult (id=🐉🐉🐉)'
Пример #11
0
def test_credential_encryption_with_ask(organization_factory, credentialtype_ssh):
    org = organization_factory('test').organization
    cred = Credential(credential_type=credentialtype_ssh, name="Bob's Credential", inputs={'password': '******'}, organization=org)
    cred.save()

    assert Credential.objects.count() == 1
    cred = Credential.objects.all()[:1].get()
    assert cred.inputs['password'] == 'ASK'
Пример #12
0
def test_clean_credential_with_invalid_type_xfail(credentialtype_aws,
                                                  job_template):
    credential = Credential(name='My Credential',
                            credential_type=credentialtype_aws)
    credential.save()

    with pytest.raises(ValidationError):
        job_template.credential = credential
        job_template.full_clean()
Пример #13
0
def galaxy_credential():
    galaxy_type = CredentialType.objects.create(kind='galaxy')
    cred = Credential(created=now(),
                      modified=now(),
                      name='Ansible Galaxy',
                      managed=True,
                      credential_type=galaxy_type,
                      inputs={'url': 'https://galaxy.ansible.com/'})
    cred.save()
Пример #14
0
def test_credential_encryption(organization_factory, credentialtype_ssh):
    org = organization_factory('test').organization
    cred = Credential(credential_type=credentialtype_ssh, name="Bob's Credential", inputs={'password': '******'}, organization=org)
    cred.save()

    assert Credential.objects.count() == 1
    cred = Credential.objects.all()[:1].get()
    assert cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'password') == 'testing123'
Пример #15
0
def mk_credential(name, credential_type='ssh', persisted=True):
    if persisted:
        type_, status = CredentialType.objects.get_or_create(kind=credential_type)
        type_.save()
    else:
        type_ = CredentialType.defaults[credential_type]()
    cred = Credential(credential_type=type_, name=name)
    if persisted:
        cred.save()
    return cred
def test_prompted_credential_replaced_on_launch(get, post, job_template, admin, machine_credential):
    # If a JT has a credential that needs a password, but the launch POST
    # specifies credential that does not require any passwords
    cred2 = Credential(name='second-cred', inputs=machine_credential.inputs, credential_type=machine_credential.credential_type)
    cred2.inputs['password'] = '******'
    cred2.save()
    job_template.credentials.add(cred2)
    url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk})
    resp = post(url, {}, admin, expect=400)
    resp = post(url, {'credentials': [machine_credential.pk]}, admin, expect=201)
    assert 'job' in resp.data
Пример #17
0
def test_credential_with_multiple_secrets(organization_factory, credentialtype_ssh):
    org = organization_factory('test').organization
    cred = Credential(
        credential_type=credentialtype_ssh, name="Bob's Credential", inputs={'ssh_key_data': 'SOMEKEY', 'ssh_key_unlock': 'testing123'}, organization=org
    )
    cred.save()

    assert Credential.objects.count() == 1
    cred = Credential.objects.all()[:1].get()

    assert cred.inputs['ssh_key_data'].startswith('$encrypted$')
    assert decrypt_field(cred, 'ssh_key_data') == 'SOMEKEY'
    assert cred.inputs['ssh_key_unlock'].startswith('$encrypted$')
    assert decrypt_field(cred, 'ssh_key_unlock') == 'testing123'
Пример #18
0
def job_template_with_ids(job_template_factory):
    # Create non-persisted objects with IDs to send to job_template_factory
    credential = Credential(id=1, pk=1, name='testcred', kind='ssh')
    net_cred = Credential(id=2, pk=2, name='testnetcred', kind='net')
    cloud_cred = Credential(id=3, pk=3, name='testcloudcred', kind='aws')
    vault_cred = Credential(id=4, pk=4, name='testnetcred', kind='vault')
    inv = Inventory(id=11, pk=11, name='testinv')
    proj = Project(id=14, pk=14, name='testproj')

    jt_objects = job_template_factory(
        'testJT', project=proj, inventory=inv, credential=credential,
        cloud_credential=cloud_cred, network_credential=net_cred,
        persisted=False)
    jt_objects.job_template.vault_credential = vault_cred
    return jt_objects.job_template
def test_custom_cred_with_empty_encrypted_field():
    ct = CredentialType(name='My Custom Cred',
                        kind='custom',
                        inputs={
                            'fields': [{
                                'id': 'some_field',
                                'label': 'My Field',
                                'secret': True
                            }]
                        })
    cred = Credential(id=4,
                      name='Testing 1 2 3',
                      credential_type=ct,
                      inputs={})
    assert cred.encrypt_field('some_field', None) is None
Пример #20
0
def test_ssh_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'ssh'):
        cred.__dict__.update({
            'username': '******',
            'password': '******',
            'ssh_key_data': EXAMPLE_PRIVATE_KEY,
            'ssh_key_unlock': 'keypass',
            'become_method': 'sudo',
            'become_username': '******',
            'become_password': '******',
        })

    assert cred.credential_type.name == 'Machine'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'password') == 'secret'
    assert cred.inputs['ssh_key_data'].startswith('$encrypted$')
    assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
    assert cred.inputs['ssh_key_unlock'].startswith('$encrypted$')
    assert decrypt_field(cred, 'ssh_key_unlock') == 'keypass'
    assert cred.inputs['become_method'] == 'sudo'
    assert cred.inputs['become_username'] == 'superuser'
    assert cred.inputs['become_password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'become_password') == 'superpassword'
    assert Credential.objects.count() == 1
Пример #21
0
def test_credential_creation_validation_failure(inputs):
    type_ = CredentialType(
        kind='cloud',
        name='SomeCloud',
        managed=True,
        inputs={
            'fields': [{
                'id': 'username',
                'label': 'Username for SomeCloud',
                'type': 'string'
            }, {
                'id': 'flag',
                'label': 'Some Boolean Flag',
                'type': 'boolean'
            }]
        },
    )
    cred = Credential(credential_type=type_,
                      name="Bob's Credential",
                      inputs=inputs)
    field = cred._meta.get_field('inputs')

    with pytest.raises(Exception) as e:
        field.validate(inputs, cred)
    assert e.type in (ValidationError, DRFValidationError)
Пример #22
0
def test_cloud_credential_type_mutability(patch, organization, admin, credentialtype_ssh,
                                          credentialtype_aws):
    cred = Credential(
        credential_type=credentialtype_aws,
        name='Best credential ever',
        organization=organization,
        inputs={
            'username': u'jim',
            'password': u'pass'
        }
    )
    cred.save()

    jt = JobTemplate()
    jt.save()
    jt.credentials.add(cred)

    def _change_credential_type():
        return patch(
            reverse('api:credential_detail', kwargs={'pk': cred.pk}),
            {
                'credential_type': credentialtype_ssh.pk,
                'inputs': {
                    'username': u'jim',
                    'password': u'pass'
                }
            },
            admin
        )

    response = _change_credential_type()
    assert response.status_code == 400
    expected = ['You cannot change the credential type of the credential, '
                'as it may break the functionality of the resources using it.']
    assert response.data['credential_type'] == expected

    response = patch(
        reverse('api:credential_detail', kwargs={'pk': cred.pk}),
        {'name': 'Worst credential ever'},
        admin
    )
    assert response.status_code == 200
    assert Credential.objects.get(pk=cred.pk).name == 'Worst credential ever'

    jt.delete()
    response = _change_credential_type()
    assert response.status_code == 200
Пример #23
0
def credential():
    ssh_type = CredentialType.defaults['ssh']()
    return Credential(
        id=43,
        name='example-cred',
        credential_type=ssh_type,
        inputs={'username': '******', 'password': '******'}
    )
def test_invalid_credential_type_at_launch(get, post, job_template, admin,
                                           kind):
    cred_type = CredentialType.defaults[kind]()
    cred_type.save()
    cred = Credential(name='Some Cred',
                      credential_type=cred_type,
                      inputs={
                          'username': '******',
                          'password': '******',
                      })
    cred.save()
    url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk})

    resp = post(url, {'credentials': [cred.pk]}, admin, expect=400)
    assert 'Cannot assign a Credential of kind `{}`'.format(
        kind) in resp.data.get('credentials', [])
    assert Job.objects.count() == 0
Пример #25
0
def test_clean_credential_with_custom_types(credentialtype_aws,
                                            credentialtype_net, job_template):
    aws = Credential(name='AWS Credential', credential_type=credentialtype_aws)
    aws.save()
    net = Credential(name='Net Credential', credential_type=credentialtype_net)
    net.save()

    job_template.extra_credentials.add(aws)
    job_template.extra_credentials.add(net)
    job_template.full_clean()
Пример #26
0
def test_invalid_clean_insights_credential():
    cred_type = CredentialType.defaults['scm']()
    cred = Credential(credential_type=cred_type)
    inv = Inventory(insights_credential=cred)

    with pytest.raises(ValidationError) as e:
        inv.clean_insights_credential()

    assert json.dumps(str(e.value)) == json.dumps(str([u"Credential kind must be 'insights'."]))
Пример #27
0
def test_invalid_kind_clean_insights_credential():
    cred_type = CredentialType.defaults['insights']()
    insights_cred = Credential(credential_type=cred_type)
    inv = Inventory(kind='smart', insights_credential=insights_cred)

    with pytest.raises(ValidationError) as e:
        inv.clean_insights_credential()

    assert json.dumps(str(e.value)) == json.dumps(str([u'Assignment not allowed for Smart Inventory']))
Пример #28
0
def test_vault_validation(organization, inputs, valid):
    cred_type = CredentialType.defaults['vault']()
    cred_type.save()
    cred = Credential(credential_type=cred_type, name="Best credential ever", inputs=inputs, organization=organization)
    cred.save()
    if valid:
        cred.full_clean()
    else:
        with pytest.raises(Exception) as e:
            cred.full_clean()
        assert e.type in (ValidationError, serializers.ValidationError)
Пример #29
0
def test_vault_only_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'ssh'):
        cred.__dict__.update({
            'vault_password': '******',
        })

    assert cred.credential_type.name == 'Vault'
    assert cred.inputs['vault_password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'vault_password') == 'vault'
    assert Credential.objects.count() == 1
def test_cred_unique_org_name_kind(organization_factory, credentialtype_ssh):
    objects = organization_factory("test")

    cred = Credential(name="test",
                      credential_type=credentialtype_ssh,
                      organization=objects.organization)
    cred.save()

    with pytest.raises(IntegrityError):
        cred = Credential(name="test",
                          credential_type=credentialtype_ssh,
                          organization=objects.organization)
        cred.save()