Пример #1
0
def default_acl(*args, **kwargs):
    """ Default ACLs for confidant: always return true for users, but enforce
    ACLs for services, restricting access to:

    * resource_type: service
      actions: metadata, get
    """
    resource_type = kwargs.get('resource_type')
    action = kwargs.get('action')
    resource_id = kwargs.get('resource_id')
    # Some ACL checks also pass extra args in via kwargs, which we would
    # access via:
    #    resource_kwargs = kwargs.get('kwargs')
    if authnz.user_is_user_type('user'):
        return True
    elif authnz.user_is_user_type('service'):
        if resource_type == 'service' and action in ['metadata', 'get']:
            # Does the resource ID match the authenticated username?
            if authnz.user_is_service(resource_id):
                return True
        # We currently only allow services to access service get/metadata
        return False
    else:
        # This should never happen, but paranoia wins out
        return False
Пример #2
0
def default_acl(*args, **kwargs):
    """ Default ACLs for confidant: Allow access to all resource types
    and actions for users, except for certificate resource_type. Deny access
    to all resource types and actions for services, except:

    * resource_type: service
      actions: metadata, get
      resource_id: must match logged-in user's username
    * resource_type: certificate
      actions: get
      resource_id: must match against ACM_PRIVATE_CA_DOMAIN_REGEX setting
          for the CA for the CN in the CSR, and for all SAN values in the CSR,
          and the server_name named group in the regex must match the logged
          in user's username.
      kwargs (ca): CA used for this get
      kwargs (san): A list of subject alternative names in the CSR
    """
    resource_type = kwargs.get('resource_type')
    action = kwargs.get('action')
    resource_id = kwargs.get('resource_id')
    resource_kwargs = kwargs.get('kwargs')
    if authnz.user_is_user_type('user'):
        if resource_type == 'certificate':
            return False
        elif resource_type == 'ca':
            return False
        return True
    elif authnz.user_is_user_type('service'):
        if resource_type == 'service' and action in ['metadata', 'get']:
            # Does the resource ID match the authenticated username?
            if authnz.user_is_service(resource_id):
                return True
        elif resource_type == 'ca' and action in ['list', 'get']:
            return True
        elif resource_type == 'certificate' and action in ['get']:
            ca_object = certificatemanager.get_ca(resource_kwargs.get('ca'))
            # Require a name pattern
            if not ca_object.settings['name_regex']:
                return False
            cert_pattern = re.compile(ca_object.settings['name_regex'])
            domains = [resource_id]
            domains.extend(resource_kwargs.get('san', []))
            # Ensure the CN and every value in the SAN is allowed for this
            # user.
            for domain in domains:
                match = cert_pattern.match(domain)
                if not match:
                    return False
                service_name = match.group('service_name')
                if not service_name:
                    return False
                if not authnz.user_is_service(service_name):
                    return False
            return True
        return False
    else:
        # This should never happen, but paranoia wins out
        return False
Пример #3
0
 def test_user_is_user_type(self):
     app.config['USE_AUTH'] = False
     self.assertTrue(authnz.user_is_user_type('anything'))
     app.config['USE_AUTH'] = True
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'user'
         self.assertTrue(authnz.user_is_user_type('user'))
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'service'
         self.assertTrue(authnz.user_is_user_type('service'))
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'user'
         self.assertFalse(authnz.user_is_user_type('service'))
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'service'
         self.assertFalse(authnz.user_is_user_type('user'))
Пример #4
0
 def test_user_is_user_type(self):
     app.config['USE_AUTH'] = False
     self.assertTrue(authnz.user_is_user_type('anything'))
     app.config['USE_AUTH'] = True
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'user'
         self.assertTrue(authnz.user_is_user_type('user'))
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'service'
         self.assertTrue(authnz.user_is_user_type('service'))
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'user'
         self.assertFalse(authnz.user_is_user_type('service'))
     with patch('confidant.authnz.g') as g_mock:
         g_mock.user_type = 'service'
         self.assertFalse(authnz.user_is_user_type('user'))
Пример #5
0
def test_user_is_user_type(mocker):
    mocker.patch('confidant.authnz.settings.USE_AUTH', False)
    assert authnz.user_is_user_type('anything') is True

    mocker.patch('confidant.authnz.settings.USE_AUTH', True)
    app = create_app()
    with app.app_context():
        g_mock = mocker.patch('confidant.authnz.g')
        g_mock.user_type = 'user'
        assert authnz.user_is_user_type('user') is True

        g_mock.user_type = 'service'
        assert authnz.user_is_user_type('service') is True

        g_mock.user_type = 'user'
        assert authnz.user_is_user_type('service') is False

        g_mock.user_type = 'service'
        assert authnz.user_is_user_type('user') is False
Пример #6
0
def get_service(id):
    '''
    Get service metadata and all credentials for this service. This endpoint
    allows basic authentication.
    '''
    #_init_.py에 정의된 user_is_user_type함수를 통해 service값이라면 제어문 안으로
    if authnz.user_is_user_type('service'):
        #_init_.py에 정의된 user_is_service함수를 통해 함수의 파라메터 값으로 받아온 id가 아니라면 로그에 'Authz failed for service {0}.', 'Authenticated user is not authorized.'라는 메시지와 함께 401error를 띄운다
        if not authnz.user_is_service(id):
            logging.warning('Authz failed for service {0}.'.format(id))
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    try:
        #service라는 변수에 id값 대입
        service = Service.get(id)
        #_init_.py에 정의된 service_in_account함수를 통해 account값이 일치하지 않는다면 제어문 안으로
        if not authnz.service_in_account(service.account):
            #아래와 같은 로그를 남긴다
            logging.warning(
                'Authz failed for service {0} (wrong account).'.format(id)
            )
            #msg에 아래와 같은 문자 대입
            msg = 'Authenticated user is not authorized.'
            #401error를 msg에 대입된 문자열과 함께 jsonify시켜 리턴
            return jsonify({'error': msg}), 401
    #위 try문의 코드에 error발생 시 예외처리
    except DoesNotExist:
        return jsonify({}), 404
    if (service.data_type != 'service' and
            service.data_type != 'archive-service'):
        return jsonify({}), 404
    logging.debug('Authz succeeded for service {0}.'.format(id))
    try:
        #credential을 가져온다
        credentials = _get_credentials(service.credentials)
    except KeyError:
        #error발생 시 500error발생
        logging.exception('KeyError occurred in getting credentials')
        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,
        'enabled': service.enabled,
        'revision': service.revision,
        'modified_date': service.modified_date,
        'modified_by': service.modified_by
    })
Пример #7
0
def get_service(id):
    '''
    Get service metadata and all credentials for this service. This endpoint
    allows basic authentication.
    '''
    if authnz.user_is_user_type('service'):
        if not authnz.user_is_service(id):
            logging.warning('Authz failed for service {0}.'.format(id))
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    try:
        service = Service.get(id)
        if not authnz.service_in_account(service.account):
            logging.warning(
                'Authz failed for service {0} (wrong account).'.format(id)
            )
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    except DoesNotExist:
        return jsonify({}), 404
    if (service.data_type != 'service' and
            service.data_type != 'archive-service'):
        return jsonify({}), 404
    logging.debug('Authz succeeded for service {0}.'.format(id))
    try:
        credentials = _get_credentials(service.credentials)
    except KeyError:
        logging.exception('KeyError occurred in getting credentials')
        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,
        'enabled': service.enabled,
        'revision': service.revision,
        'modified_date': service.modified_date,
        'modified_by': service.modified_by
    })
Пример #8
0
Файл: v1.py Проект: ab/confidant
def get_service(id):
    '''
    Get service metadata and all credentials for this service. This endpoint
    allows basic authentication.
    '''
    if authnz.user_is_user_type('service'):
        if not authnz.user_is_service(id):
            logging.warning('Authz failed for service {0}.'.format(id))
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    try:
        service = Service.get(id)
        if not authnz.service_in_account(service.account):
            logging.warning(
                'Authz failed for service {0} (wrong account).'.format(id)
            )
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    except Service.DoesNotExist:
        return jsonify({}), 404
    if (service.data_type != 'service' and
            service.data_type != 'archive-service'):
        return jsonify({}), 404
    logging.debug('Authz succeeded for service {0}.'.format(id))
    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,
        'enabled': service.enabled,
        'revision': service.revision,
        'modified_date': service.modified_date,
        'modified_by': service.modified_by
    })
Пример #9
0
def get_service(id):
    '''
    Get a service object from the provided service ID.

    .. :quickref: Service; Get a service object from the provided service ID.

    **Example request**:

    .. sourcecode:: http

       GET /v1/services/example-development

    :param id: The service ID to get.
    :type id: str
    :query boolean metadata_only: If true, only fetch metadata for this
      service, and do not respond with decrypted credential pairs in the
      credential responses.

    **Example response**:

    .. sourcecode:: http

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

       {
         "id": "example-development",
         "revision": 1,
         "enabled": true,
         "modified_date": "2019-12-16T23:16:11.413299+00:00",
         "modified_by": "*****@*****.**",
         "account": null,
         "credentials": [
           {
             "id": "abcd12345bf4f1cafe8e722d3860404",
             "name": "Example Credential",
             "credential_keys": ["test_key"],
             "credential_pairs": {
               "test_key": "test_value"
             },
             "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": {}
           },
           ...
         ],
         "blind_credentials": [],
         "permissions": {
           "metadata": true,
           "get": true,
           "update": true
         }
       }

    :resheader Content-Type: application/json
    :statuscode 200: Success
    :statuscode 403: Client does not have permissions to get the service ID
                     provided.
    '''
    permissions = {
        'metadata': False,
        'get': False,
        'update': False,
    }
    metadata_only = misc.get_boolean(request.args.get('metadata_only'))
    logged_in_user = authnz.get_logged_in_user()
    action = 'metadata' if metadata_only else 'get'
    permissions['metadata'] = acl_module_check(
        resource_type='service',
        action='metadata',
        resource_id=id,
    )
    permissions['get'] = acl_module_check(
        resource_type='service',
        action='get',
        resource_id=id,
    )
    if not permissions[action]:
        msg = "{} does not have access to get service {}".format(
            authnz.get_logged_in_user(),
            id
        )
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403

    logger.info(
        'get_service called on id={} by user={} metadata_only={}'.format(
            id,
            logged_in_user,
            metadata_only,
        )
    )
    try:
        service = Service.get(id)
        if not authnz.service_in_account(service.account):
            logger.warning(
                'Authz failed for service {0} (wrong account).'.format(id)
            )
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    except DoesNotExist:
        return jsonify({}), 404
    if (service.data_type != 'service' and
            service.data_type != 'archive-service'):
        return jsonify({}), 404
    logger.debug('Authz succeeded for service {0}.'.format(id))
    try:
        credentials = credentialmanager.get_credentials(service.credentials)
    except KeyError:
        logger.exception('KeyError occurred in getting credentials')
        return jsonify({'error': 'Decryption error.'}), 500
    blind_credentials = credentialmanager.get_blind_credentials(
        service.blind_credentials,
    )
    # TODO: this check can be expensive, so we're gating only to user auth.
    # We should probably add an argument that opts in for permission hints,
    # rather than always checking them.
    if authnz.user_is_user_type('user'):
        combined_cred_ids = (
            list(service.credentials) + list(service.blind_credentials)
        )
        permissions['update'] = acl_module_check(
            resource_type='service',
            action='update',
            resource_id=id,
            kwargs={
                'credential_ids': combined_cred_ids,
            },
        )
    service_response = ServiceResponse.from_service_expanded(
        service,
        credentials=credentials,
        blind_credentials=blind_credentials,
        metadata_only=metadata_only,
    )
    service_response.permissions = permissions
    return service_expanded_response_schema.dumps(service_response)
Пример #10
0
def get_service(id):
    '''
    Get service metadata and all credentials for this service. This endpoint
    allows basic authentication.
    '''
    permissions = {
        'metadata': False,
        'get': False,
        'update': False,
    }
    metadata_only = request.args.get('metadata_only', default=False, type=bool)
    logged_in_user = authnz.get_logged_in_user()
    action = 'metadata' if metadata_only else 'get'
    permissions['metadata'] = acl_module_check(
        resource_type='service',
        action='metadata',
        resource_id=id,
    )
    permissions['get'] = acl_module_check(
        resource_type='service',
        action='get',
        resource_id=id,
    )
    if not permissions[action]:
        msg = "{} does not have access to get service {}".format(
            authnz.get_logged_in_user(), id)
        error_msg = {'error': msg, 'reference': id}
        return jsonify(error_msg), 403

    logging.info(
        'get_service called on id={} by user={} metadata_only={}'.format(
            id,
            logged_in_user,
            metadata_only,
        ))
    try:
        service = Service.get(id)
        if not authnz.service_in_account(service.account):
            logging.warning(
                'Authz failed for service {0} (wrong account).'.format(id))
            msg = 'Authenticated user is not authorized.'
            return jsonify({'error': msg}), 401
    except DoesNotExist:
        return jsonify({}), 404
    if (service.data_type != 'service'
            and service.data_type != 'archive-service'):
        return jsonify({}), 404
    logging.debug('Authz succeeded for service {0}.'.format(id))
    try:
        credentials = credentialmanager.get_credentials(service.credentials)
    except KeyError:
        logging.exception('KeyError occurred in getting credentials')
        return jsonify({'error': 'Decryption error.'}), 500
    blind_credentials = credentialmanager.get_blind_credentials(
        service.blind_credentials, )
    # TODO: this check can be expensive, so we're gating only to user auth.
    # We should probably add an argument that opts in for permission hints,
    # rather than always checking them.
    if authnz.user_is_user_type('user'):
        combined_cred_ids = (list(service.credentials) +
                             list(service.blind_credentials))
        permissions['update'] = acl_module_check(
            resource_type='service',
            action='update',
            resource_id=id,
            kwargs={
                'credential_ids': combined_cred_ids,
            },
        )
    service_response = ServiceResponse.from_service_expanded(
        service,
        credentials=credentials,
        blind_credentials=blind_credentials,
        metadata_only=metadata_only,
    )
    service_response.permissions = permissions
    return service_expanded_response_schema.dumps(service_response)