Ejemplo n.º 1
0
def test_credential_get_input(organization_factory):
    organization = organization_factory('test').organization
    type_ = CredentialType(kind='vault',
                           name='somevault',
                           managed_by_tower=True,
                           inputs={
                               'fields': [{
                                   'id': 'vault_password',
                                   'type': 'string',
                                   'secret': True,
                               }, {
                                   'id': 'vault_id',
                                   'type': 'string',
                                   'secret': False
                               }, {
                                   'id': 'secret',
                                   'type': 'string',
                                   'secret': True,
                               }]
                           })
    type_.save()

    cred = Credential(organization=organization,
                      credential_type=type_,
                      name="Bob's Credential",
                      inputs={'vault_password': '******'})
    cred.save()
    cred.full_clean()

    assert isinstance(cred, Credential)
    # verify expected exception is raised when attempting to access an unset
    # input without providing a default
    with pytest.raises(AttributeError):
        cred.get_input('vault_id')
    # verify that the provided default is used for unset inputs
    assert cred.get_input('vault_id', default='foo') == 'foo'
    # verify expected exception is raised when attempting to access an undefined
    # input without providing a default
    with pytest.raises(AttributeError):
        cred.get_input('field_not_on_credential_type')
    # verify that the provided default is used for undefined inputs
    assert cred.get_input('field_not_on_credential_type',
                          default='bar') == 'bar'
    # verify expected exception is raised when attempting to access an unset secret
    # input without providing a default
    with pytest.raises(AttributeError):
        cred.get_input('secret')
    # verify that the provided default is used for undefined inputs
    assert cred.get_input('secret', default='fiz') == 'fiz'
    # verify return values for encrypted secret fields are decrypted
    assert cred.inputs['vault_password'].startswith('$encrypted$')
    assert cred.get_input('vault_password') == 'testing321'
Ejemplo n.º 2
0
def test_azure_classic_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'azure'):
        cred.__dict__.update({
            'username': '******',
            'ssh_key_data': EXAMPLE_PRIVATE_KEY
        })

    assert cred.credential_type.name == 'Microsoft Azure Classic (deprecated)'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['ssh_key_data'].startswith('$encrypted$')
    assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
    assert Credential.objects.count() == 1
Ejemplo n.º 3
0
def test_choices_validity(become_method, valid, organization):
    inputs = {'become_method': become_method}
    cred_type = CredentialType.defaults['ssh']()
    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(serializers.ValidationError) as e:
            cred.full_clean()
        assert "'%s' is not one of" % become_method in str(e)
Ejemplo n.º 4
0
def test_credential_creation(organization_factory):
    org = organization_factory('test').organization
    type_ = CredentialType(
        kind='cloud', name='SomeCloud', managed_by_tower=True, inputs={'fields': [{'id': 'username', 'label': 'Username for SomeCloud', 'type': 'string'}]}
    )
    type_.save()

    cred = Credential(credential_type=type_, name="Bob's Credential", inputs={'username': '******'}, organization=org)
    cred.save()
    cred.full_clean()
    assert isinstance(cred, Credential)
    assert cred.name == "Bob's Credential"
    assert cred.inputs['username'] == 'bob'
Ejemplo n.º 5
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'
Ejemplo n.º 6
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)
Ejemplo n.º 7
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'
Ejemplo n.º 8
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'
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
Ejemplo n.º 10
0
def test_credential_creation_validation_failure(inputs):
    type_ = CredentialType(
        kind='cloud',
        name='SomeCloud',
        managed_by_tower=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)
Ejemplo n.º 11
0
def test_gce_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'gce'):
        cred.__dict__.update({
            'username': '******',
            'project': 'PROJECT-123',
            'ssh_key_data': EXAMPLE_PRIVATE_KEY
        })

    assert cred.credential_type.name == 'Google Compute Engine'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['project'] == 'PROJECT-123'
    assert cred.inputs['ssh_key_data'].startswith('$encrypted$')
    assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
    assert Credential.objects.count() == 1
Ejemplo n.º 12
0
def test_cloudforms_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'cloudforms'):
        cred.__dict__.update({
            'username': '******',
            'password': '******',
            'host': 'https://example.org/',
        })

    assert cred.credential_type.name == 'Red Hat CloudForms'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'password') == 'secret'
    assert cred.inputs['host'] == 'https://example.org/'
    assert Credential.objects.count() == 1
Ejemplo n.º 13
0
def test_aws_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'aws'):
        cred.__dict__.update({
            'username': '******',
            'password': '******',
            'security_token': 'secret-token'
        })

    assert cred.credential_type.name == 'Amazon Web Services'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'password') == 'secret'
    assert cred.inputs['security_token'].startswith('$encrypted$')
    assert decrypt_field(cred, 'security_token') == 'secret-token'
    assert Credential.objects.count() == 1
Ejemplo n.º 14
0
def test_ssh_key_data_validation(organization, kind, ssh_key_data, ssh_key_unlock, valid):
    inputs = {'username': '******'}
    if ssh_key_data:
        inputs['ssh_key_data'] = ssh_key_data
    if ssh_key_unlock:
        inputs['ssh_key_unlock'] = ssh_key_unlock
    cred_type = CredentialType.defaults[kind]()
    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)
Ejemplo n.º 15
0
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
Ejemplo n.º 16
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
Ejemplo n.º 17
0
def test_openstack_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'openstack'):
        cred.__dict__.update({
            'username': '******',
            'password': '******',
            'host': 'https://keystone.example.org/',
            'project': 'TENANT_ID',
        })

    assert cred.credential_type.name == 'OpenStack'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'password') == 'secret'
    assert cred.inputs['host'] == 'https://keystone.example.org/'
    assert cred.inputs['project'] == 'TENANT_ID'
    assert Credential.objects.count() == 1
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
Ejemplo n.º 19
0
def test_scm_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'scm'):
        cred.__dict__.update({
            'username': '******',
            'password': '******',
            'ssh_key_data': EXAMPLE_PRIVATE_KEY,
            'ssh_key_unlock': 'keypass',
        })

    assert cred.credential_type.name == 'Source Control'
    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 Credential.objects.count() == 1
Ejemplo n.º 20
0
def test_azure_rm_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'azure_rm'):
        cred.__dict__.update({
            'subscription': 'some-subscription',
            'username': '******',
            'password': '******',
            'client': 'some-client',
            'secret': 'some-secret',
            'tenant': 'some-tenant',
        })

    assert cred.credential_type.name == 'Microsoft Azure Resource Manager'
    assert cred.inputs['subscription'] == 'some-subscription'
    assert cred.inputs['username'] == 'bob'
    assert cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'password') == 'some-password'
    assert cred.inputs['client'] == 'some-client'
    assert cred.inputs['secret'].startswith('$encrypted$')
    assert decrypt_field(cred, 'secret') == 'some-secret'
    assert cred.inputs['tenant'] == 'some-tenant'
    assert Credential.objects.count() == 1
Ejemplo n.º 21
0
def test_vault_with_ssh_migration():
    cred = Credential(name='My Credential')
    with migrate(cred, 'ssh'):
        cred.__dict__.update({
            'vault_password': '******',
            'username': '******',
            'password': '******',
            'ssh_key_data': EXAMPLE_PRIVATE_KEY,
            'ssh_key_unlock': 'keypass',
            'become_method': 'sudo',
            'become_username': '******',
            'become_password': '******',
        })
    assert Credential.objects.count() == 2

    assert Credential.objects.filter(
        credential_type__name='Vault').get() == cred
    assert cred.inputs.keys() == ['vault_password']
    assert cred.inputs['vault_password'].startswith('$encrypted$')
    assert decrypt_field(cred, 'vault_password') == 'vault'

    ssh_cred = Credential.objects.filter(credential_type__name='Machine').get()
    assert sorted(ssh_cred.inputs.keys()) == sorted(
        CredentialType.from_v1_kind('ssh').defined_fields)
    assert ssh_cred.credential_type.name == 'Machine'
    assert ssh_cred.inputs['username'] == 'bob'
    assert ssh_cred.inputs['password'].startswith('$encrypted$')
    assert decrypt_field(ssh_cred, 'password') == 'secret'
    assert ssh_cred.inputs['ssh_key_data'].startswith('$encrypted$')
    assert decrypt_field(ssh_cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
    assert ssh_cred.inputs['ssh_key_unlock'].startswith('$encrypted$')
    assert decrypt_field(ssh_cred, 'ssh_key_unlock') == 'keypass'
    assert ssh_cred.inputs['become_method'] == 'sudo'
    assert ssh_cred.inputs['become_username'] == 'superuser'
    assert ssh_cred.inputs['become_password'].startswith('$encrypted$')
    assert decrypt_field(ssh_cred, 'become_password') == 'superpassword'
Ejemplo n.º 22
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

                default_ee = settings.AWX_EXECUTION_ENVIRONMENT_DEFAULT_IMAGE
                ee, created = ExecutionEnvironment.objects.get_or_create(
                    name='Default EE',
                    defaults={
                        'image': default_ee,
                        'managed_by_tower': True
                    })

                if created:
                    changed = True
                    print('Default Execution Environment registered.')

        if changed:
            print('(changed: True)')
        else:
            print('(changed: False)')
Ejemplo n.º 23
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()
Ejemplo n.º 24
0
def test_valid_clean_insights_credential():
    cred_type = CredentialType.defaults['insights']()
    insights_cred = Credential(credential_type=cred_type)
    inv = Inventory(insights_credential=insights_cred)

    inv.clean_insights_credential()