Ejemplo n.º 1
0
def get_ca(ca):
    '''
    Get the CA information for the provided ca.
    '''
    try:
        ca_object = certificatemanager.get_ca(ca)
    except certificatemanager.CertificateAuthorityNotFoundError:
        return jsonify({'error': 'Provided CA not found.'}), 404

    logged_in_user = authnz.get_logged_in_user()
    if not acl_module_check(
            resource_type='ca',
            action='get',
            resource_id=ca,
    ):
        msg = '{} does not have access to get ca {}'.format(
            authnz.get_logged_in_user(),
            ca,
        )
        error_msg = {'error': msg, 'reference': ca}
        return jsonify(error_msg), 403

    logging.info('get_ca called on id={} by user={}'.format(
        ca,
        logged_in_user,
    ))

    _ca = ca_object.get_certificate_authority_certificate()
    ca_response = CertificateAuthorityResponse(
        ca=_ca['ca'],
        certificate=_ca['certificate'],
        certificate_chain=_ca['certificate_chain'],
        tags=_ca['tags'],
    )
    return certificate_authority_response_schema.dumps(ca_response)
Ejemplo n.º 2
0
Archivo: v1.py Proyecto: ab/confidant
def create_credential():
    data = request.get_json()
    if not data.get('credential_pairs'):
        return jsonify({'error': 'credential_pairs is a required field'}), 400
    if not isinstance(data.get('metadata', {}), dict):
        return jsonify({'error': 'metadata must be a dict'}), 400
    # Ensure credential pair keys are lowercase
    credential_pairs = _lowercase_credential_pairs(data['credential_pairs'])
    _check, ret = _check_credential_pair_values(credential_pairs)
    if not _check:
        return jsonify(ret), 400
    for cred in Credential.data_type_date_index.query(
            'credential', name__eq=data['name']):
        # Conflict, the name already exists
        msg = 'Name already exists. See id: {0}'.format(cred.id)
        return jsonify({'error': msg, 'reference': cred.id}), 409
    # Generate an initial stable ID to allow name changes
    id = str(uuid.uuid4()).replace('-', '')
    # Try to save to the archive
    revision = 1
    credential_pairs = json.dumps(credential_pairs)
    data_key = keymanager.create_datakey(encryption_context={'id': id})
    cipher = CipherManager(data_key['plaintext'], version=2)
    credential_pairs = cipher.encrypt(credential_pairs)
    cred = Credential(
        id='{0}-{1}'.format(id, revision),
        data_type='archive-credential',
        name=data['name'],
        credential_pairs=credential_pairs,
        metadata=data.get('metadata'),
        revision=revision,
        enabled=data.get('enabled'),
        data_key=data_key['ciphertext'],
        cipher_version=2,
        modified_by=authnz.get_logged_in_user()
    ).save(id__null=True)
    # Make this the current revision
    cred = Credential(
        id=id,
        data_type='credential',
        name=data['name'],
        credential_pairs=credential_pairs,
        metadata=data.get('metadata'),
        revision=revision,
        enabled=data.get('enabled'),
        data_key=data_key['ciphertext'],
        cipher_version=2,
        modified_by=authnz.get_logged_in_user()
    )
    cred.save()
    return jsonify({
        'id': cred.id,
        'name': cred.name,
        'credential_pairs': json.loads(cipher.decrypt(cred.credential_pairs)),
        'metadata': cred.metadata,
        'revision': cred.revision,
        'enabled': cred.enabled,
        'modified_date': cred.modified_date,
        'modified_by': cred.modified_by
    })
Ejemplo n.º 3
0
def create_credential():
    data = request.get_json()
    if not data.get('credential_pairs'):
        return jsonify({'error': 'credential_pairs is a required field'}), 400
    if not isinstance(data.get('metadata', {}), dict):
        return jsonify({'error': 'metadata must be a dict'}), 400
    # Ensure credential pair keys are lowercase
    credential_pairs = _lowercase_credential_pairs(data['credential_pairs'])
    _check, ret = _check_credential_pair_values(credential_pairs)
    if not _check:
        return jsonify(ret), 400
    for cred in Credential.data_type_date_index.query(
            'credential', name__eq=data['name']):
        # Conflict, the name already exists
        msg = 'Name already exists. See id: {0}'.format(cred.id)
        return jsonify({'error': msg, 'reference': cred.id}), 409
    # Generate an initial stable ID to allow name changes
    id = str(uuid.uuid4()).replace('-', '')
    # Try to save to the archive
    revision = 1
    credential_pairs = json.dumps(credential_pairs)
    data_key = keymanager.create_datakey(encryption_context={'id': id})
    cipher = CipherManager(data_key['plaintext'], version=2)
    credential_pairs = cipher.encrypt(credential_pairs)
    cred = Credential(
        id='{0}-{1}'.format(id, revision),
        data_type='archive-credential',
        name=data['name'],
        credential_pairs=credential_pairs,
        metadata=data.get('metadata'),
        revision=revision,
        enabled=data.get('enabled'),
        data_key=data_key['ciphertext'],
        cipher_version=2,
        modified_by=authnz.get_logged_in_user()
    ).save(id__null=True)
    # Make this the current revision
    cred = Credential(
        id=id,
        data_type='credential',
        name=data['name'],
        credential_pairs=credential_pairs,
        metadata=data.get('metadata'),
        revision=revision,
        enabled=data.get('enabled'),
        data_key=data_key['ciphertext'],
        cipher_version=2,
        modified_by=authnz.get_logged_in_user()
    )
    cred.save()
    return jsonify({
        'id': cred.id,
        'name': cred.name,
        'credential_pairs': json.loads(cipher.decrypt(cred.credential_pairs)),
        'metadata': cred.metadata,
        'revision': cred.revision,
        'enabled': cred.enabled,
        'modified_date': cred.modified_date,
        'modified_by': cred.modified_by
    })
Ejemplo n.º 4
0
def get_certificate_from_csr(ca):
    '''
    Get a certificate from the ca provided in the url, using the CSR, validity
    and san provided in the POST body.
    '''
    try:
        ca_object = certificatemanager.get_ca(ca)
    except certificatemanager.CertificateAuthorityNotFoundError:
        return jsonify({'error': 'Provided CA not found.'}), 404
    data = request.get_json()
    if not data or not data.get('csr'):
        return jsonify(
            {'error': 'csr must be provided in the POST body.'}, ), 400
    validity = data.get(
        'validity',
        ca_object.settings['max_validity_days'],
    )
    try:
        csr = ca_object.decode_csr(data['csr'])
    except Exception:
        logging.exception('Failed to decode PEM csr')
        return jsonify({'error': 'csr could not be decoded'}, ), 400
    # Get the cn and san values from the csr object, so that we can use them
    # for the ACL check.
    cn = ca_object.get_csr_common_name(csr)
    san = ca_object.get_csr_san(csr)

    logged_in_user = authnz.get_logged_in_user()
    if not acl_module_check(
            resource_type='certificate',
            action='get',
            resource_id=cn,
            kwargs={
                'ca': ca,
                'san': san,
            },
    ):
        msg = ('{} does not have access to get certificate cn {} against'
               ' ca {}').format(
                   authnz.get_logged_in_user(),
                   cn,
                   ca,
               )
        error_msg = {'error': msg, 'reference': cn}
        return jsonify(error_msg), 403

    logging.info('get_certificate called on id={} for ca={} by user={}'.format(
        cn,
        ca,
        logged_in_user,
    ))

    arn = ca_object.issue_certificate(data['csr'], validity)
    certificate = ca_object.get_certificate_from_arn(arn)
    certificate_response = CertificateResponse(
        certificate=certificate['certificate'],
        certificate_chain=certificate['certificate_chain'],
    )
    return certificate_response_schema.dumps(certificate_response)
Ejemplo n.º 5
0
def get_certificate(ca, cn):
    '''
    Get a certificate for the provided cn, using the provided CA.
    '''
    try:
        ca_object = certificatemanager.get_ca(ca)
    except certificatemanager.CertificateAuthorityNotFoundError:
        return jsonify({'error': 'Provided CA not found.'}), 404
    san = request.args.getlist('san')

    logged_in_user = authnz.get_logged_in_user()
    if not acl_module_check(
            resource_type='certificate',
            action='get',
            resource_id=cn,
            kwargs={
                'ca': ca,
                'san': san,
            },
    ):
        msg = ('{} does not have access to get certificate cn {} against'
               ' ca {}').format(
                   authnz.get_logged_in_user(),
                   cn,
                   ca,
               )
        error_msg = {'error': msg, 'reference': cn}
        return jsonify(error_msg), 403

    logging.info('get_certificate called on id={} for ca={} by user={}'.format(
        cn,
        ca,
        logged_in_user,
    ))

    validity = request.args.get(
        'validity',
        default=ca_object.settings['max_validity_days'],
        type=int,
    )
    try:
        certificate = ca_object.issue_certificate_with_key(
            cn,
            validity,
            san,
        )
    except certificatemanager.CertificateNotReadyError:
        # Ratelimit response for a locked certificate in the cache
        error_msg = 'Certificate being requested, please wait and try again.'
        response = jsonify(error_msg)
        response.retry_after = 2
        return response, 429
    certificate_response = CertificateResponse(
        certificate=certificate['certificate'],
        certificate_chain=certificate['certificate_chain'],
        key=certificate['key'],
    )
    return certificate_expanded_response_schema.dumps(certificate_response)
Ejemplo n.º 6
0
def test_get_logged_in_user(mocker):
    mocker.patch('confidant.authnz.settings.USER_EMAIL_SUFFIX', 'example.com')
    app = create_app()
    with app.test_request_context('/v1/user/email'):
        with pytest.raises(authnz.UserUnknownError):
            authnz.get_logged_in_user()
        g_mock = mocker.patch('confidant.authnz.g')
        g_mock.username = '******'
        assert authnz.get_logged_in_user() == 'unittestuser'
Ejemplo n.º 7
0
 def test_get_logged_in_user(self):
     with app.test_request_context('/v1/user/email'):
         with self.assertRaises(authnz.UserUnknownError):
             authnz.get_logged_in_user()
         with patch('confidant.authnz.g') as g_mock:
             g_mock.username = '******'
             self.assertEqual(authnz.get_logged_in_user(), 'unittestuser')
         session_data = {'user': {'email': '*****@*****.**'}}
         with patch('confidant.authnz.userauth.session', session_data):
             self.assertEqual(authnz.get_logged_in_user(),
                              '*****@*****.**')
Ejemplo n.º 8
0
def list_cas():
    '''
    List the configured CAs.

    .. :quickref: Certificate Authorities; Get a list of the detailed
                  certificate authorities configured on the server.

    **Example request**:

    .. sourcecode:: http

       GET /v1/cas

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "cas": [
           "example-ca": {
             "certificate": "---...BEGIN...",
             "certificate_chain": "---...BEGIN...",
             "tags": {
               "hello": "world"
            },
            ...
         ]
       }

    :resheader Content-Type: application/json
    :statuscode 200: success
    :statuscode 403: client does not have access to list CAs
    '''

    logged_in_user = authnz.get_logged_in_user()
    if not acl_module_check(
            resource_type='ca',
            action='list',
    ):
        msg = '{} does not have access to list cas'.format(
            authnz.get_logged_in_user(), )
        error_msg = {'error': msg}
        return jsonify(error_msg), 403

    cas = certificatemanager.list_cas()

    logger.info('list_cas called by user={}'.format(logged_in_user))

    cas_response = CertificateAuthoritiesResponse.from_cas(cas)
    return certificate_authorities_response_schema.dumps(cas_response)
Ejemplo n.º 9
0
    def test_will_extract_from_request(self):
        with app.test_request_context('/fake'):
            # No headers given: an error
            with self.assertRaises(authnz.UserUnknownError):
                authnz.get_logged_in_user()

            # Both headers given: success
            with patch('confidant.authnz.userauth.request') as request_mock:
                request_mock.headers = {
                    app.config['HEADER_AUTH_USERNAME_HEADER']: 'unittestuser',
                    app.config['HEADER_AUTH_EMAIL_HEADER']: '*****@*****.**',
                }
                self.assertEqual(authnz.get_logged_in_user(), '*****@*****.**')
Ejemplo n.º 10
0
def test_header_auth_will_extract_from_request(mocker, mock_header_auth):
    app = create_app()
    with app.test_request_context('/fake'):
        # No headers given: an error
        with pytest.raises(authnz.UserUnknownError):
            authnz.get_logged_in_user()

        # Both headers given: success
        request_mock = mocker.patch('confidant.authnz.userauth.request')
        request_mock.headers = {
            'X-Confidant-Username': '******',
            'X-Confidant-Email': '*****@*****.**',  # noqa:E501
        }
        assert authnz.get_logged_in_user() == '*****@*****.**'
Ejemplo n.º 11
0
 def test_get_logged_in_user(self):
     with app.test_request_context('/v1/user/email'):
         with self.assertRaises(authnz.UserUnknownError):
             authnz.get_logged_in_user()
         with patch('confidant.authnz.g') as g_mock:
             g_mock.username = '******'
             self.assertEqual(authnz.get_logged_in_user(), 'unittestuser')
         session_data = {
             'user': {'email': '*****@*****.**'}
         }
         with patch('confidant.authnz.userauth.session', session_data):
             self.assertEqual(
                 authnz.get_logged_in_user(),
                 '*****@*****.**'
             )
Ejemplo n.º 12
0
def ensure_grants(id):
    # we pass [] in for the credential IDs, because this action isn't related
    # to adding or removing credentials, but just a generic update of a
    # service.
    if not acl_module_check(resource_type='service',
                            action='update',
                            resource_id=id,
                            kwargs={
                                'credential_ids': [],
                            }):
        msg = "{} does not have access to ensure grants for service {}"
        msg = msg.format(authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
    except DoesNotExist:
        msg = 'id provided does not exist.'
        return jsonify({'error': msg}), 400
    try:
        keymanager.ensure_grants(id)
    except keymanager.ServiceCreateGrantError:
        msg = 'Failed to add grants for service.'
        logging.error(msg)
        return jsonify({'error': msg}), 400
    try:
        grants = keymanager.grants_exist(id)
    except keymanager.ServiceGetGrantError:
        msg = 'Failed to get grants.'
        return jsonify({'error': msg}), 500
    return jsonify({'id': id, 'grants': grants})
Ejemplo n.º 13
0
def get_archive_service_revisions(id):
    if not acl_module_check(resource_type='service',
                            action='metadata',
                            resource_id=id):
        msg = "{} does not have access to service {} revisions".format(
            authnz.get_logged_in_user(),
            id
        )
        error_msg = {'error': msg}
        return jsonify(error_msg), 403
    try:
        service = Service.get(id)
    except DoesNotExist:
        logging.warning(
            'Item with id {0} does not exist.'.format(id)
        )
        return jsonify({}), 404
    if (service.data_type != 'service' and
            service.data_type != 'archive-service'):
        return jsonify({}), 404
    _range = range(1, service.revision + 1)
    ids = []
    for i in _range:
        ids.append("{0}-{1}".format(id, i))
    revisions_response = RevisionsResponse.from_services(
        Service.batch_get(ids)
    )
    return revisions_response_schema.dumps(revisions_response)
Ejemplo n.º 14
0
def get_archive_service_list():
    if not acl_module_check(resource_type='service', action='list'):
        msg = "{} does not have access to list services".format(
            authnz.get_logged_in_user())
        error_msg = {'error': msg}
        return jsonify(error_msg), 403
    limit = request.args.get(
        'limit',
        default=settings.HISTORY_PAGE_LIMIT,
        type=int,
    )
    page = request.args.get('page', default=None, type=str)
    if page:
        try:
            page = decode_last_evaluated_key(page)
        except Exception:
            logging.exception('Failed to parse provided page')
            return jsonify({'error': 'Failed to parse page'}), 400
    results = Service.data_type_date_index.query(
        'archive-service',
        scan_index_forward=False,
        limit=limit,
        last_evaluated_key=page,
    )
    services_response = ServicesResponse.from_services(
        [service for service in results],
        next_page=results.last_evaluated_key,
    )
    return services_response_schema.dumps(services_response)
Ejemplo n.º 15
0
def get_credential_list():
    """
    Returns a list of the metadata of all the current revision of credentials.

    .. :quickref: Credentials; Get a list of the metadata for all current
                  credential revisions.

    **Example request**:

    .. sourcecode:: http

       GET /v1/credentials

    :query string next_page: If paged results were returned in a call, this
                             query string can be used to fetch the next page.

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "credentials": [
           {
             "id": "abcd12345bf4f1cafe8e722d3860404",
             "name": "Example Credential",
             "credential_keys": [],
             "credential_pairs": {},
             "metadata": {
               "example_metadata_key": "example_value"
             },
             "revision": 1,
             "enabled": true,
             "documentation": "Example documentation",
             "modified_date": "2019-12-16T23:16:11.413299+00:00",
             "modified_by": "*****@*****.**",
             "permissions": {}
           },
           ...
         ],
         next_page: null
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 403: Client does not have permissions to list credentials.
    """
    if not acl_module_check(resource_type='credential', action='list'):
        msg = "{} does not have access to list credentials".format(
            authnz.get_logged_in_user())
        error_msg = {'error': msg}
        return jsonify(error_msg), 403

    credentials_response = CredentialsResponse.from_credentials([
        credential
        for credential in Credential.data_type_date_index.query('credential')
    ])
    return credentials_response_schema.dumps(credentials_response)
Ejemplo n.º 16
0
def get_user_info():
    '''
    Get the email associated with the currently authenticated user.

    .. :quickref: Email Address; Get the email address associated with the
                  currently authenticated user.

    **Example request**:

    .. sourcecode:: http

       GET /v1/user/email

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "email": "*****@*****.**"
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    '''
    try:
        response = jsonify({'email': authnz.get_logged_in_user()})
    except authnz.UserUnknownError:
        response = jsonify({'email': None})
    return response
Ejemplo n.º 17
0
def get_grants(id):
    if not acl_module_check(
          resource_type='service',
          action='metadata',
          resource_id=id,
    ):
        msg = "{} does not have access to get grants for service {}"
        msg = msg.format(authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
    except DoesNotExist:
        msg = 'id provided does not exist.'
        return jsonify({'error': msg}), 400
    try:
        grants = keymanager.grants_exist(id)
    except keymanager.ServiceGetGrantError:
        msg = 'Failed to get grants.'
        return jsonify({'error': msg}), 500
    return jsonify({
        'id': id,
        'grants': grants
    })
Ejemplo n.º 18
0
def diff_service(id, old_revision, new_revision):
    if not acl_module_check(resource_type='service',
                            action='metadata',
                            resource_id=id):
        msg = "{} does not have access to diff service {}".format(
            authnz.get_logged_in_user(),
            id
        )
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403

    try:
        old_service = Service.get('{}-{}'.format(id, old_revision))
    except DoesNotExist:
        return jsonify({'error': 'Service not found.'}), 404
    if old_service.data_type != 'archive-service':
        msg = 'id provided is not a service.'
        return jsonify({'error': msg}), 400
    try:
        new_service = Service.get('{}-{}'.format(id, new_revision))
    except DoesNotExist:
        logging.warning(
            'Item with id {0} does not exist.'.format(id)
        )
        return jsonify({}), 404
    if new_service.data_type != 'archive-service':
        msg = 'id provided is not a service.'
        return jsonify({'error': msg}), 400
    return jsonify(old_service.diff(new_service))
Ejemplo n.º 19
0
def test_get_logged_in_user_from_session(mocker):
    mocker.patch('confidant.authnz.settings.USER_EMAIL_SUFFIX', 'example.com')
    app = create_app()
    with app.test_request_context('/v1/user/email'):
        session_data = {'user': {'email': '*****@*****.**'}}
        mocker.patch('confidant.authnz.userauth.session', session_data)
        assert authnz.get_logged_in_user() == '*****@*****.**'
Ejemplo n.º 20
0
    def test_will_extract_from_request(self):
        with app.test_request_context('/fake'):
            # No headers given: an error
            with self.assertRaises(authnz.UserUnknownError):
                authnz.get_logged_in_user()

            # Both headers given: success
            with patch('confidant.authnz.userauth.request') as request_mock:
                request_mock.headers = {
                    app.config['HEADER_AUTH_USERNAME_HEADER']:
                    'unittestuser',
                    app.config['HEADER_AUTH_EMAIL_HEADER']:
                    '*****@*****.**',
                }
                self.assertEqual(authnz.get_logged_in_user(),
                                 '*****@*****.**')
Ejemplo n.º 21
0
Archivo: v1.py Proyecto: ab/confidant
def get_user_info():
    '''
    Get the email address of the currently logged-in user.
    '''
    try:
        response = jsonify({'email': authnz.get_logged_in_user()})
    except authnz.UserUnknownError:
        response = jsonify({'email': None})
    return response
Ejemplo n.º 22
0
def get_user_info():
    '''
    Get the email address of the currently logged-in user.
    '''
    try:
        response = jsonify({'email': authnz.get_logged_in_user()})
    except authnz.UserUnknownError:
        response = jsonify({'email': None})
    return response
Ejemplo n.º 23
0
def get_iam_roles_list():
    if not acl_module_check(resource_type='service', action='list'):
        msg = "{} does not have access to list services".format(
            authnz.get_logged_in_user())
        error_msg = {'error': msg}
        return jsonify(error_msg), 403

    roles = iamrolemanager.get_iam_roles()
    return jsonify({'roles': roles})
Ejemplo n.º 24
0
def get_service_list():
    if not acl_module_check(resource_type='service', action='list'):
        msg = "{} does not have access to list services".format(
            authnz.get_logged_in_user())
        error_msg = {'error': msg}
        return jsonify(error_msg), 403
    services_response = ServicesResponse.from_services(
        Service.data_type_date_index.query('service'))
    return services_response_schema.dumps(services_response)
Ejemplo n.º 25
0
def get_credential(id):
    if not acl_module_check(
            resource_type='credential', action='metadata', resource_id=id):
        msg = "{} does not have access to credential {}".format(
            authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403

    try:
        credential = Credential.get(id)
    except DoesNotExist:
        logging.warning('Item with id {0} does not exist.'.format(id))
        return jsonify({}), 404
    if (credential.data_type != 'credential'
            and credential.data_type != 'archive-credential'):
        return jsonify({}), 404

    permissions = {
        'metadata':
        True,
        'get':
        False,
        'update':
        acl_module_check(resource_type='credential',
                         action='update',
                         resource_id=id),
    }
    include_credential_pairs = False
    if acl_module_check(resource_type='credential',
                        action='get',
                        resource_id=id):
        permissions['get'] = True
        include_credential_pairs = True
        log_line = "{0} get credential {1}".format(authnz.get_logged_in_user(),
                                                   id)
        logging.info(log_line)
    credential_response = CredentialResponse.from_credential(
        credential,
        include_credential_keys=True,
        include_credential_pairs=include_credential_pairs,
    )
    credential_response.permissions = permissions
    return credential_response_schema.dumps(credential_response)
Ejemplo n.º 26
0
def get_service_list():
    """
    Get a list of current service revisions.

    .. :quickref: Services; Get a list of current service revisions.

    **Example request**:

    .. sourcecode:: http

       GET /v1/services

    :query string next_page: If paged results were returned in a call, this
                             query string can be used to fetch the next page.

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "services": [
           {
             "id": "example-development",
             "revision": 1,
             "enabled": true,
             "modified_date": "2019-12-16T23:16:11.413299+00:00",
             "modified_by": "*****@*****.**",
             "account": null,
             "credentials": [],
             "blind_credentials": [],
             "permissions": {}
           },
           ...
         ],
         "next_page": null
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 403: Client does not have permissions to list services.
    """
    if not acl_module_check(resource_type='service',
                            action='list'):
        msg = "{} does not have access to list services".format(
            authnz.get_logged_in_user()
        )
        error_msg = {'error': msg}
        return jsonify(error_msg), 403
    services_response = ServicesResponse.from_services(
        Service.data_type_date_index.query('service')
    )
    return services_response_schema.dumps(services_response)
Ejemplo n.º 27
0
def get_credential_dependencies(id):
    if not acl_module_check(
            resource_type='credential', action='metadata', resource_id=id):
        msg = "{} does not have access to get dependencies for credential {}"
        msg = msg.format(authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403

    services = servicemanager.get_services_for_credential(id)
    _services = [{'id': x.id, 'enabled': x.enabled} for x in services]
    return jsonify({'services': _services})
Ejemplo n.º 28
0
def get_user_info():
    '''
    Get the email address of the currently logged-in user.
    '''
    try:
        #email에 대한 JSON타입의 http response 생성된 값을 response변수에 대입
        response = jsonify({'email': authnz.get_logged_in_user()})
    except authnz.UserUnknownError:
        #UserUnknownError가 뜰 시 none을 response변수에 대입
        response = jsonify({'email': None})
    #response 변수 리턴
    return response
Ejemplo n.º 29
0
def get_credential_list():
    if not acl_module_check(resource_type='credential', action='list'):
        msg = "{} does not have access to list credentials".format(
            authnz.get_logged_in_user())
        error_msg = {'error': msg}
        return jsonify(error_msg), 403

    credentials_response = CredentialsResponse.from_credentials([
        credential
        for credential in Credential.data_type_date_index.query('credential')
    ])
    return credentials_response_schema.dumps(credentials_response)
Ejemplo n.º 30
0
def list_cas():
    '''
    List the configured CAs.
    '''

    logged_in_user = authnz.get_logged_in_user()
    if not acl_module_check(
            resource_type='ca',
            action='list',
    ):
        msg = '{} does not have access to list cas'.format(
            authnz.get_logged_in_user(), )
        error_msg = {'error': msg}
        return jsonify(error_msg), 403

    cas = certificatemanager.list_cas()

    logging.info('list_cas called by user={}'.format(logged_in_user))

    cas_response = CertificateAuthoritiesResponse.from_cas(cas)
    return certificate_authorities_response_schema.dumps(cas_response)
Ejemplo n.º 31
0
def get_iam_roles_list():
    """
    Get a list of IAM roles from the configured AWS account.

    .. :quickref: IAM Roles; Get a list of IAM roles from the configured
                  AWS account.

    **Example request**:

    .. sourcecode:: http

       GET /v1/roles

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "roles": [
           'example-development',
           'example2-development',
           ...
         ]
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 403: Client does not have permissions to list services.
    """
    if not acl_module_check(resource_type='service',
                            action='list'):
        msg = "{} does not have access to list services".format(
            authnz.get_logged_in_user()
        )
        error_msg = {'error': msg}
        return jsonify(error_msg), 403

    roles = iamrolemanager.get_iam_roles()
    return jsonify({'roles': roles})
Ejemplo n.º 32
0
def get_credential_dependencies(id):
    """
    Returns a list of services that this credential is mapped to.

    .. :quickref: Credential Mappings; Get a list of services that this
                  credential is mapped to.

    **Example request**:

    .. sourcecode:: http

       GET /v1/credentials/abcd12345bf4f1cafe8e722d3860404/services

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "services": ["example-development", "example2-development"]
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 403: Client does not have permissions to get metadata for the
                     provided credential.
    """
    if not acl_module_check(
            resource_type='credential', action='metadata', resource_id=id):
        msg = "{} does not have access to get dependencies for credential {}"
        msg = msg.format(authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403

    services = servicemanager.get_services_for_credential(id)
    _services = [{'id': x.id, 'enabled': x.enabled} for x in services]
    return jsonify({'services': _services})
Ejemplo n.º 33
0
def get_grants(id):
    """
    Get grants for the provided service ID.

    .. :quickref: KMS Grants; Get grants for the provided service ID.

    **Example request**:

    .. sourcecode:: http

       GET /v1/grants/example-development

    :param id: The service ID to ensure grants for.
    :type id: str

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "id": "example-development",
         "grants": {
           "encrypt_grant": true,
           "decrypt_grant": true
         }
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 400: Invalid input. The service provided does not exist.
    :statuscode 403: Client does not have permissions to get service metadata
                     for the specified service ID.
    """
    if not acl_module_check(
          resource_type='service',
          action='metadata',
          resource_id=id,
    ):
        msg = "{} does not have access to get grants for service {}"
        msg = msg.format(authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
    except DoesNotExist:
        msg = 'id provided does not exist.'
        return jsonify({'error': msg}), 400
    try:
        grants = keymanager.grants_exist(id)
    except keymanager.ServiceGetGrantError:
        msg = 'Failed to get grants.'
        return jsonify({'error': msg}), 500
    return jsonify({
        'id': id,
        'grants': grants
    })
Ejemplo n.º 34
0
def ensure_grants(id):
    """
    Ensure grants are set for the provided service ID.

    .. :quickref: KMS Grants; Ensure grants are set for the provided service ID.

    **Example request**:

    .. sourcecode:: http

       PUT /v1/grants/example-development

    :param id: The service ID to ensure grants for.
    :type id: str

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

       {
         "id": "example-development",
         "grants": {
           "encrypt_grant": true,
           "decrypt_grant": true
         }
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 400: Invalid input. The service provided does not exist.
    :statuscode 403: Client does not have permissions to create or update the
                     specified service ID.
    """
    # we pass [] in for the credential IDs, because this action isn't related
    # to adding or removing credentials, but just a generic update of a
    # service.
    if not acl_module_check(
          resource_type='service',
          action='update',
          resource_id=id,
          kwargs={
              'credential_ids': [],
          }
    ):
        msg = "{} does not have access to ensure grants for service {}"
        msg = msg.format(authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
    except DoesNotExist:
        msg = 'id provided does not exist.'
        return jsonify({'error': msg}), 400
    try:
        keymanager.ensure_grants(id)
    except keymanager.ServiceCreateGrantError:
        msg = 'Failed to add grants for service.'
        logger.error(msg)
        return jsonify({'error': msg}), 400
    try:
        grants = keymanager.grants_exist(id)
    except keymanager.ServiceGetGrantError:
        msg = 'Failed to get grants.'
        return jsonify({'error': msg}), 500
    return jsonify({
        'id': id,
        'grants': grants
    })
Ejemplo n.º 35
0
Archivo: v1.py Proyecto: ab/confidant
def update_blind_credential(id):
    try:
        _cred = BlindCredential.get(id)
    except Credential.DoesNotExist:
        return jsonify({'error': 'Blind credential not found.'}), 404
    if _cred.data_type != 'blind-credential':
        msg = 'id provided is not a blind-credential.'
        return jsonify({'error': msg}), 400
    data = request.get_json()
    update = {}
    revision = _get_latest_blind_credential_revision(id, _cred.revision)
    update['name'] = data.get('name', _cred.name)
    if 'enabled' in data:
        if not isinstance(data['enabled'], bool):
            return jsonify({'error': 'Enabled must be a boolean.'}), 400
        update['enabled'] = data['enabled']
    else:
        update['enabled'] = _cred.enabled
    if not isinstance(data.get('metadata', {}), dict):
        return jsonify({'error': 'metadata must be a dict'}), 400
    services = _get_services_for_blind_credential(id)
    if 'credential_pairs' in data:
        for key in ['data_key', 'cipher_type', 'cipher_version']:
            if key not in data:
                msg = '{0} required when updating credential_pairs.'
                msg = msg.format(key)
                return jsonify({'error': msg}), 400
        update['credential_pairs'] = data['credential_pairs']
        update['credential_keys'] = data.get('credential_keys', [])
        if not isinstance(update['credential_keys'], list):
            return jsonify({
                'error': 'credential_keys must be a list.'
            }), 400
        # Ensure credential keys don't conflicts with pairs from other
        # services
        conflicts = _pair_key_conflicts_for_services(
            id,
            data['credential_keys'],
            services
        )
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400
        if not isinstance(data['data_key'], dict):
            return jsonify({
                'error': 'data_key must be a dict with a region/key mapping.'
            }), 400
        update['data_key'] = data['data_key']
        update['cipher_type'] = data['cipher_type']
        update['cipher_version'] = data['cipher_version']
    else:
        update['credential_pairs'] = _cred.credential_pairs
        update['credential_keys'] = _cred.credential_keys
        update['data_key'] = _cred.data_key
        update['cipher_type'] = _cred.cipher_type
        update['cipher_version'] = _cred.cipher_version
    update['metadata'] = data.get('metadata', _cred.metadata)
    # Try to save to the archive
    try:
        BlindCredential(
            id='{0}-{1}'.format(id, revision),
            data_type='archive-blind-credential',
            name=update['name'],
            credential_pairs=update['credential_pairs'],
            credential_keys=update['credential_keys'],
            metadata=update['metadata'],
            revision=revision,
            enabled=update['enabled'],
            data_key=update['data_key'],
            cipher_type=update['cipher_type'],
            cipher_version=update['cipher_version'],
            modified_by=authnz.get_logged_in_user()
        ).save(id__null=True)
    except PutError as e:
        logging.error(e)
        return jsonify(
            {'error': 'Failed to add blind-credential to archive.'}
        ), 500
    try:
        cred = BlindCredential(
            id=id,
            data_type='blind-credential',
            name=update['name'],
            credential_pairs=update['credential_pairs'],
            credential_keys=update['credential_keys'],
            metadata=update['metadata'],
            revision=revision,
            enabled=update['enabled'],
            data_key=update['data_key'],
            cipher_type=update['cipher_type'],
            cipher_version=update['cipher_version'],
            modified_by=authnz.get_logged_in_user()
        )
        cred.save()
    except PutError as e:
        logging.error(e)
        return jsonify(
            {'error': 'Failed to update active blind-credential.'}
        ), 500
    if services:
        service_names = [x.id for x in services]
        msg = 'Updated credential "{0}" ({1}); Revision {2}'
        msg = msg.format(cred.name, cred.id, cred.revision)
        graphite.send_event(service_names, msg)
        webhook.send_event('blind_credential_update', service_names, [cred.id])
    return jsonify({
        'id': cred.id,
        'name': cred.name,
        'credential_pairs': cred.credential_pairs,
        'credential_keys': list(cred.credential_keys),
        'cipher_type': cred.cipher_type,
        'cipher_version': cred.cipher_version,
        'metadata': cred.metadata,
        'revision': cred.revision,
        'enabled': cred.enabled,
        'data_key': cred.data_key,
        'modified_date': cred.modified_date,
        'modified_by': cred.modified_by
    })
Ejemplo n.º 36
0
Archivo: v1.py Proyecto: ab/confidant
def map_service_credentials(id):
    data = request.get_json()
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
        revision = _service.revision + 1
        _service_credential_ids = _service.credentials
    except Service.DoesNotExist:
        revision = 1
        _service_credential_ids = []

    if data.get('credentials') or data.get('blind_credentials'):
        conflicts = _pair_key_conflicts_for_credentials(
            data.get('credentials', []),
            data.get('blind_credentials', []),
        )
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400

    accounts = app.config['SCOPED_AUTH_KEYS'].values()
    if data.get('account') and data['account'] not in accounts:
        ret = {'error': '{0} is not a valid account.'}
        return jsonify(ret), 400

    # If this is the first revision, we should attempt to create a grant for
    # this service.
    if revision == 1:
        try:
            keymanager.ensure_grants(id)
        except keymanager.ServiceCreateGrantError:
            msg = 'Failed to add grants for {0}.'.format(id)
            logging.error(msg)
    # Try to save to the archive
    try:
        Service(
            id='{0}-{1}'.format(id, revision),
            data_type='archive-service',
            credentials=data.get('credentials'),
            blind_credentials=data.get('blind_credentials'),
            account=data.get('account'),
            enabled=data.get('enabled'),
            revision=revision,
            modified_by=authnz.get_logged_in_user()
        ).save(id__null=True)
    except PutError as e:
        logging.error(e)
        return jsonify({'error': 'Failed to add service to archive.'}), 500

    try:
        service = Service(
            id=id,
            data_type='service',
            credentials=data.get('credentials'),
            blind_credentials=data.get('blind_credentials'),
            account=data.get('account'),
            enabled=data.get('enabled'),
            revision=revision,
            modified_by=authnz.get_logged_in_user()
        )
        service.save()
    except PutError as e:
        logging.error(e)
        return jsonify({'error': 'Failed to update active service.'}), 500
    added = list(set(service.credentials) - set(_service_credential_ids))
    removed = list(set(_service_credential_ids) - set(service.credentials))
    msg = 'Added credentials: {0}; Removed credentials {1}; Revision {2}'
    msg = msg.format(added, removed, service.revision)
    graphite.send_event([id], msg)
    webhook.send_event('service_update', [service.id], service.credentials)
    try:
        credentials = _get_credentials(service.credentials)
    except KeyError:
        return jsonify({'error': 'Decryption error.'}), 500
    blind_credentials = _get_blind_credentials(service.blind_credentials)
    return jsonify({
        'id': service.id,
        'account': service.account,
        'credentials': credentials,
        'blind_credentials': blind_credentials,
        'revision': service.revision,
        'enabled': service.enabled,
        'modified_date': service.modified_date,
        'modified_by': service.modified_by
    })
Ejemplo n.º 37
0
Archivo: v1.py Proyecto: ab/confidant
def create_blind_credential():
    data = request.get_json()
    missing = []
    for arg in ['cipher_version', 'cipher_type', 'credential_pairs',
                'data_key']:
        if not data.get(arg):
            missing.append(arg)
    if missing:
        return jsonify({
            'error': 'The following fields are required: {0}'.format(missing)
        }), 400
    if not isinstance(data['data_key'], dict):
        return jsonify({
            'error': 'data_key must be a dict with a region/key mapping.'
        }), 400
    if not isinstance(data.get('credential_keys', []), list):
        return jsonify({
            'error': 'credential_keys must be a list.'
        }), 400
    if not isinstance(data.get('metadata', {}), dict):
        return jsonify({'error': 'metadata must be a dict'}), 400
    for cred in BlindCredential.data_type_date_index.query(
            'blind-credential', name__eq=data['name']):
        # Conflict, the name already exists
        msg = 'Name already exists. See id: {0}'.format(cred.id)
        return jsonify({'error': msg, 'reference': cred.id}), 409
    # Generate an initial stable ID to allow name changes
    id = str(uuid.uuid4()).replace('-', '')
    # Try to save to the archive
    revision = 1
    cred = BlindCredential(
        id='{0}-{1}'.format(id, revision),
        data_type='archive-blind-credential',
        name=data['name'],
        credential_pairs=data['credential_pairs'],
        credential_keys=data.get('credential_keys'),
        metadata=data.get('metadata'),
        revision=revision,
        enabled=data.get('enabled'),
        data_key=data['data_key'],
        cipher_type=data['cipher_type'],
        cipher_version=data['cipher_version'],
        modified_by=authnz.get_logged_in_user()
    ).save(id__null=True)
    # Make this the current revision
    cred = BlindCredential(
        id=id,
        data_type='blind-credential',
        name=data['name'],
        credential_pairs=data['credential_pairs'],
        credential_keys=data.get('credential_keys'),
        metadata=data.get('metadata'),
        revision=revision,
        enabled=data.get('enabled'),
        data_key=data['data_key'],
        cipher_type=data['cipher_type'],
        cipher_version=data['cipher_version'],
        modified_by=authnz.get_logged_in_user()
    )
    cred.save()
    return jsonify({
        'id': cred.id,
        'name': cred.name,
        'credential_pairs': cred.credential_pairs,
        'credential_keys': list(cred.credential_keys),
        'cipher_type': cred.cipher_type,
        'cipher_version': cred.cipher_version,
        'metadata': cred.metadata,
        'revision': cred.revision,
        'enabled': cred.enabled,
        'data_key': cred.data_key,
        'modified_date': cred.modified_date,
        'modified_by': cred.modified_by
    })
Ejemplo n.º 38
0
Archivo: v1.py Proyecto: ab/confidant
def update_credential(id):
    try:
        _cred = Credential.get(id)
    except Credential.DoesNotExist:
        return jsonify({'error': 'Credential not found.'}), 404
    if _cred.data_type != 'credential':
        msg = 'id provided is not a credential.'
        return jsonify({'error': msg}), 400
    data = request.get_json()
    update = {}
    revision = _get_latest_credential_revision(id, _cred.revision)
    update['name'] = data.get('name', _cred.name)
    if 'enabled' in data:
        if not isinstance(data['enabled'], bool):
            return jsonify({'error': 'Enabled must be a boolean.'}), 400
        update['enabled'] = data['enabled']
    else:
        update['enabled'] = _cred.enabled
    if not isinstance(data.get('metadata', {}), dict):
        return jsonify({'error': 'metadata must be a dict'}), 400
    services = _get_services_for_credential(id)
    if 'credential_pairs' in data:
        # Ensure credential pair keys are lowercase
        credential_pairs = _lowercase_credential_pairs(
            data['credential_pairs']
        )
        _check, ret = _check_credential_pair_values(credential_pairs)
        if not _check:
            return jsonify(ret), 400
        # Ensure credential pairs don't conflicts with pairs from other
        # services
        conflicts = _pair_key_conflicts_for_services(
            id,
            credential_pairs.keys(),
            services
        )
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400
        update['credential_pairs'] = json.dumps(credential_pairs)
    else:
        data_key = keymanager.decrypt_datakey(
            _cred.data_key,
            encryption_context={'id': id}
        )
        cipher_version = _cred.cipher_version
        cipher = CipherManager(data_key, cipher_version)
        update['credential_pairs'] = cipher.decrypt(_cred.credential_pairs)
    data_key = keymanager.create_datakey(encryption_context={'id': id})
    cipher = CipherManager(data_key['plaintext'], version=2)
    credential_pairs = cipher.encrypt(update['credential_pairs'])
    update['metadata'] = data.get('metadata', _cred.metadata)
    # Try to save to the archive
    try:
        Credential(
            id='{0}-{1}'.format(id, revision),
            name=update['name'],
            data_type='archive-credential',
            credential_pairs=credential_pairs,
            metadata=update['metadata'],
            enabled=update['enabled'],
            revision=revision,
            data_key=data_key['ciphertext'],
            cipher_version=2,
            modified_by=authnz.get_logged_in_user()
        ).save(id__null=True)
    except PutError as e:
        logging.error(e)
        return jsonify({'error': 'Failed to add credential to archive.'}), 500
    try:
        cred = Credential(
            id=id,
            name=update['name'],
            data_type='credential',
            credential_pairs=credential_pairs,
            metadata=update['metadata'],
            enabled=update['enabled'],
            revision=revision,
            data_key=data_key['ciphertext'],
            cipher_version=2,
            modified_by=authnz.get_logged_in_user()
        )
        cred.save()
    except PutError as e:
        logging.error(e)
        return jsonify({'error': 'Failed to update active credential.'}), 500
    if services:
        service_names = [x.id for x in services]
        msg = 'Updated credential "{0}" ({1}); Revision {2}'
        msg = msg.format(cred.name, cred.id, cred.revision)
        graphite.send_event(service_names, msg)
        webhook.send_event('credential_update', service_names, [cred.id])
    return jsonify({
        'id': cred.id,
        'name': cred.name,
        'credential_pairs': json.loads(cipher.decrypt(cred.credential_pairs)),
        'metadata': cred.metadata,
        'revision': cred.revision,
        'enabled': cred.enabled,
        'modified_date': cred.modified_date,
        'modified_by': cred.modified_by
    })