Exemplo n.º 1
0
    def mutate(_, info, auth_token, provider, push_token):
        authorized = False
        session_jwt = ''
        success = False

        if provider == 'google':
            try:
                user_info = id_token.verify_oauth2_token(
                    auth_token, requests.Request())

                if user_info['iss'] not in [
                        'accounts.google.com', 'https://accounts.google.com'
                ]:
                    rollbar.report_message('Error: Invalid oauth2 issuer',
                                           'error', info.context,
                                           user_info['iss'])
                    raise GraphQLError('INVALID_AUTH_TOKEN')
                if user_info['aud'] not in [
                        FI_GOOGLE_OAUTH2_KEY_ANDROID, FI_GOOGLE_OAUTH2_KEY_IOS
                ]:
                    rollbar.report_message('Error: Invalid oauth2 audience',
                                           'error', info.context,
                                           user_info['aud'])
                    raise GraphQLError('INVALID_AUTH_TOKEN')
                email = user_info['email']
                authorized = user_domain.is_registered(email)
                if push_token:
                    user_dal.update(email,
                                    {'devices_to_notify': set(push_token)})
                session_jwt = jwt.encode(
                    {
                        'user_email':
                        email,
                        'user_role':
                        user_domain.get_data(email, 'role'),
                        'company':
                        user_domain.get_data(email, 'company'),
                        'first_name':
                        user_info['given_name'],
                        'last_name':
                        user_info['family_name'],
                        'exp':
                        datetime.utcnow() +
                        timedelta(seconds=settings.SESSION_COOKIE_AGE)
                    },
                    algorithm='HS512',
                    key=settings.JWT_SECRET,
                )
                success = True
            except ValueError:
                util.cloudwatch_log(
                    info.context,
                    'Security: Sign in attempt using invalid Google token')
                raise GraphQLError('INVALID_AUTH_TOKEN')
        else:
            rollbar.report_message('Error: Unknown auth provider' + provider,
                                   'error')
            raise GraphQLError('UNKNOWN_AUTH_PROVIDER')

        return SignIn(authorized, session_jwt, success)
Exemplo n.º 2
0
    def __init__(self, project_name: str, user_email: str, role: str = None):
        self.email: str = user_email
        self.role: str = ''
        self.responsibility: str = ''
        self.phone_number: str = ''
        self.organization: str = ''
        self.first_login: str = '-'
        self.last_login: _List[int] = [-1, -1]
        self.list_projects: _List[int] = []
        if not project_name:
            projs_active = \
                ['{proj}: {description} - Active'.format(
                    proj=proj,
                    description=project_domain.get_description(proj))
                    for proj in user_domain.get_projects(self.email)]
            projs_suspended = \
                ['{proj}: {description} - Suspended'.format(
                    proj=proj,
                    description=project_domain.get_description(proj))
                    for proj in user_domain.get_projects(
                        self.email, active=False)]
            self.list_projects = projs_active + projs_suspended

        last_login = user_domain.get_data(user_email, 'last_login')

        if last_login == '1111-1-1 11:11:11' or not last_login:
            self.last_login = [-1, -1]
        else:
            dates_difference = \
                datetime.now() - datetime.strptime(last_login, '%Y-%m-%d %H:%M:%S')
            diff_last_login = [dates_difference.days, dates_difference.seconds]
            self.last_login = diff_last_login

        self.first_login = user_domain.get_data(user_email, 'date_joined')
        organization = user_domain.get_data(user_email, 'company')
        self.organization = organization.title()
        self.responsibility = has_responsibility(
            project_name, user_email) if project_name else ''
        self.phone_number = has_phone_number(user_email)
        user_role = user_domain.get_data(user_email, 'role')

        if project_name and is_customeradmin(project_name, user_email):
            self.role = 'customer_admin'
        elif user_role == 'customeradmin':
            self.role = 'customer'
        else:
            self.role = user_role

        if project_name and role:
            if role == 'admin':
                has_access = has_access_to_project(user_email, project_name,
                                                   self.role)
            else:
                has_access = user_domain.get_project_access(
                    user_email, project_name)

            if not user_domain.get_data(user_email, 'email') or \
               not has_access:
                raise UserNotFound()
def update_treatment_in_vuln(finding_id: str,
                             updated_values: Dict[str, str]) -> bool:
    new_values = cast(
        Dict[str, FindingType], {
            'treatment': updated_values.get('treatment', ''),
            'treatment_justification': updated_values.get('justification'),
            'acceptance_date': updated_values.get('acceptance_date'),
        })
    if new_values['treatment'] == 'NEW':
        new_values['treatment_manager'] = None
    vulns = get_vulnerabilities(finding_id)
    resp = True
    for vuln in vulns:
        if 'treatment_manager' not in [vuln, new_values]:
            new_values[
                'treatment_manager'] = vuln_domain.set_treatment_manager(
                    str(new_values.get('treatment', '')),
                    str(updated_values.get('user', '')),
                    finding_dal.get_finding(finding_id),
                    user_domain.get_data(str(updated_values.get('user')),
                                         'role') == 'customeradmin',
                    str(updated_values.get('user', '')))
        result_update_treatment = \
            vuln_dal.update(finding_id, str(vuln.get('UUID', '')), new_values)
        if not result_update_treatment:
            resp = False
    return resp
def set_treatment_manager(treatment: str, treatment_manager: str,
                          finding: Dict[str, FindingType],
                          is_customer_admin: bool, user_mail: str) -> str:
    if treatment == 'IN PROGRESS':
        if not is_customer_admin:
            treatment_manager = user_mail
        if treatment_manager:
            project_users = project_dal.get_users(
                str(finding.get('project_name')))
            customer_roles = ['customer', 'customeradmin']
            customer_users = \
                [user for user in project_users
                    if user_domain.get_data(user, 'role') in customer_roles]
            if treatment_manager not in customer_users:
                raise GraphQLError('Invalid treatment manager')
        else:
            raise GraphQLError('Invalid treatment manager')
    elif treatment == 'ACCEPTED':
        treatment_manager = user_mail
    elif treatment == 'ACCEPTED_UNDEFINED':
        last_state = cast(List[Dict[str, str]],
                          finding.get('historic_treatment'))[-1]
        if last_state['acceptance_status'] == 'SUBMITTED':
            treatment_manager = user_mail
        else:
            treatment_manager = last_state['user']
    return treatment_manager
 def custom_data(self, user):
     """ Send extra data to Intercom. """
     email = user.get_username()
     company = user_domain.get_data(email, 'company')
     return {
         'Company': company,
     }
Exemplo n.º 6
0
async def _resolve_fields(info, email, project_name):
    """Async resolve of fields."""
    email_dict: dict = await _get_email(email)
    role_dict: dict = await _get_role(email, project_name)
    email: str = email_dict['email']
    role: str = role_dict['role']

    if project_name and role:
        if role == 'admin':
            has_access = has_access_to_project(
                email, project_name, role)
        else:
            has_access = user_domain.get_project_access(
                email, project_name)

        if not user_domain.get_data(email, 'email') or \
                not has_access:
            raise UserNotFound()

    result = dict()
    tasks = list()
    for requested_field in info.field_nodes[0].selection_set.selections:
        snake_field = convert_camel_case_to_snake(requested_field.name.value)
        if snake_field.startswith('_'):
            continue
        resolver_func = getattr(
            sys.modules[__name__],
            f'_get_{snake_field}'
        )
        future = asyncio.ensure_future(resolver_func(email, project_name))
        tasks.append(future)
    tasks_result = await asyncio.gather(*tasks)
    for dict_result in tasks_result:
        result.update(dict_result)
    return result
Exemplo n.º 7
0
def create_user(strategy, details, backend, user=None, *args, **kwargs):
    del args
    del kwargs
    del backend
    first_name = details['first_name'][:29]
    last_name = details['last_name'][:29]
    email = details['email'].lower()

    # Put details on session.
    strategy.session_set('first_name', first_name)
    strategy.session_set('last_name', last_name)

    today = user_domain.get_current_date()
    data_dict = {
        'first_name': first_name,
        'last_login': today,
        'last_name': last_name,
        'date_joined': today
    }
    if user:
        if user_domain.get_data(str(user), 'first_name'):
            user_domain.update_last_login(user)
        else:
            user_domain.update_multiple_user_attributes(str(user), data_dict)
    else:
        mail_to = [FI_MAIL_CONTINUOUS, FI_MAIL_PROJECTS]
        name = first_name + ' ' + last_name
        context = {
            'name_user': name,
            'mail_user': email,
        }
        send_mail_new_user(mail_to, context)
        user_domain.update_multiple_user_attributes(email, data_dict)
Exemplo n.º 8
0
def create_new_user(context: Dict[str, Any], new_user_data: Dict[str, Any],
                    project_name: str) -> bool:
    analizable_list = list(new_user_data.values())[1:-1]
    if (all(validate_alphanumeric_field(field) for field in analizable_list)
            and validate_phone_field(new_user_data['phone_number'])
            and validate_email_address(new_user_data['email'])):
        email = new_user_data['email']
        organization = new_user_data['organization']
        responsibility = new_user_data['responsibility']
        role = new_user_data['role']
        phone_number = new_user_data['phone_number']
    else:
        return False

    success = False

    if not user_domain.get_data(email, 'email'):
        user_domain.create(email.lower(), {
            'company': organization.lower(),
            'phone': phone_number
        })
    if not user_domain.is_registered(email):
        user_domain.register(email)
        user_domain.assign_role(email, role)
        user_domain.update(email, organization.lower(), 'company')
    elif user_domain.is_registered(email):
        user_domain.assign_role(email, role)
    if project_name and responsibility and len(responsibility) <= 50:
        project_domain.add_access(email, project_name, 'responsibility',
                                  responsibility)
    else:
        util.cloudwatch_log(
            context,
            'Security: {email} Attempted to add responsibility to project \
                {project} without validation'.format(email=email,
                                                     project=project_name))
    if phone_number and phone_number[1:].isdigit():
        user_domain.add_phone_to_user(email, phone_number)
    if project_name and role == 'customeradmin':
        project_domain.add_user(project_name.lower(), email.lower(), role)
    if project_name and user_domain.update_project_access(
            email, project_name, True):
        description = project_domain.get_description(project_name.lower())
        project_url = \
            'https://fluidattacks.com/integrates/dashboard#!/project/' \
            + project_name.lower() + '/indicators'
        mail_to = [email]
        context = {
            'admin': email,
            'project': project_name,
            'project_description': description,
            'project_url': project_url,
        }
        email_send_thread = \
            threading.Thread(name='Access granted email thread',
                             target=send_mail_access_granted,
                             args=(mail_to, context,))
        email_send_thread.start()
        success = True
    return success
Exemplo n.º 9
0
    def resolve_remember(self, info):
        """ Resolve remember preference """
        jwt_content = util.get_jwt_content(info.context)
        user_email = jwt_content.get('user_email')
        user_info = user_domain.get_data(user_email, 'legal_remember')
        self.remember = user_info if user_info else False

        return self.remember
Exemplo n.º 10
0
def _get_recipient_first_name(email: str) -> str:
    first_name = user_domain.get_data(email, 'first_name')
    if not first_name:
        first_name = email.split('@')[0]
    else:
        # First name exists in database
        pass
    return str(first_name)
Exemplo n.º 11
0
def _send_new_event_mail(analyst: str, event_id: str, project: str,
                         subscription: str, event_type: str):
    recipients = project_dal.list_project_managers(project)
    recipients.append(analyst)
    if subscription == 'oneshot':
        recipients.append(FI_MAIL_PROJECTS)
    elif subscription == 'continuous':
        recipients += [FI_MAIL_CONTINUOUS, FI_MAIL_PROJECTS]
    if event_type in [
            'CLIENT_APPROVES_CHANGE_TOE', 'CLIENT_CANCELS_PROJECT_MILESTONE',
            'CLIENT_EXPLICITLY_SUSPENDS_PROJECT'
    ]:
        recipients.append(FI_MAIL_PRODUCTION)
        recipients += FI_MAIL_REVIEWERS.split(',')

    email_context = {
        'analyst_email':
        analyst,
        'event_id':
        event_id,
        'event_url': ('https://fluidattacks.com/integrates/dashboard#!/'
                      f'project/{project}/events/{event_id}'),
        'project':
        project
    }

    recipients_customers = [
        recipient for recipient in recipients
        if user_domain.get_data(recipient, 'role') == 'customeradmin'
    ]
    recipients_not_customers = [
        recipient for recipient in recipients
        if user_domain.get_data(recipient, 'role') != 'customeradmin'
    ]
    email_context_customers = email_context.copy()
    email_context_customers['analyst_email'] = \
        'Hacker at ' + str(user_domain.get_data(analyst, 'company')).capitalize()

    email_send_thread = threading.Thread(
        name='New event email thread',
        target=send_mail_new_event,
        args=([recipients_not_customers,
               recipients_customers], [email_context,
                                       email_context_customers]))
    email_send_thread.start()
def get_user_role(user_data: UserType) -> str:
    if user_data.get('jti'):
        role = str(
            user_domain.get_data(str(user_data.get('user_email', '')), 'role'))
        if role == 'customeradmin':
            role = 'customer'
    else:
        role = str(user_data.get('user_role', ''))
    return role
 def resolve_users(self, info):
     """ Resolve project users """
     init_email_list = project_domain.get_users(self.name)
     user_email_list = util.user_email_filter(
         init_email_list, util.get_jwt_content(info.context)['user_email'])
     self.users = [User(self.name, user_email)
                   for user_email in user_email_list
                   if user_domain.get_data(user_email, 'role')
                   in ['customer', 'customeradmin']]
     return self.users
Exemplo n.º 14
0
def _get_role(email, project_name):
    """Get role."""
    user_role = user_domain.get_data(email, 'role')
    if project_name and is_customeradmin(project_name, email):
        role = 'customer_admin'
    elif user_role == 'customeradmin':
        role = 'customer'
    else:
        role = user_role
    return dict(role=role)
Exemplo n.º 15
0
def _get_access_token(jwt_content):
    """Get access token."""
    user_email = jwt_content.get('user_email')
    access_token = user_domain.get_data(user_email, 'access_token')
    access_token_dict = {
        'hasAccessToken': bool(access_token),
        'issuedAt': str(access_token.get('iat', ''))
        if bool(access_token) else ''
    }
    return dict(access_token=json.dumps(access_token_dict))
Exemplo n.º 16
0
def _get_last_login(email, _=None):
    """Get last_login."""
    last_login = user_domain.get_data(email, 'last_login')
    if last_login == '1111-1-1 11:11:11' or not last_login:
        last_login = [-1, -1]
    else:
        dates_difference = \
            datetime.now() - datetime.strptime(last_login, '%Y-%m-%d %H:%M:%S')
        diff_last_login = [dates_difference.days, dates_difference.seconds]
        last_login = diff_last_login
    return dict(last_login=str(last_login))
Exemplo n.º 17
0
def check_registered(strategy, details, backend, *args, **kwargs):
    del args
    del kwargs
    del backend
    email = details['email'].lower()
    is_registered = user_domain.is_registered(email)
    last_login = user_domain.get_data(email, 'last_login')
    role = user_domain.get_data(email, 'role')
    company = user_domain.get_data(email, 'company')
    strategy.session_set('username', email)
    strategy.session_set('registered', is_registered)
    if role == 'customeradmin':
        role = 'customer'
    else:
        # different role
        pass
    strategy.session_set('role', role)
    strategy.session_set('company', company)
    strategy.session_set('last_login', last_login)
    strategy.session_set('projects', {})
def has_valid_access_token(email: str, context: Dict[str, str],
                           jti: str) -> bool:
    """ Verify if has active access token and match. """
    access_token = cast(Dict[str, str],
                        user_domain.get_data(email, 'access_token'))
    resp = False
    if context and access_token:
        resp = util.verificate_hash_token(access_token, jti)
    else:
        # authorization header not present or user without access_token
        pass
    return resp
Exemplo n.º 19
0
    def resolve_access_token(self, info):
        jwt_content = util.get_jwt_content(info.context)
        user_email = jwt_content.get('user_email')
        access_token = user_domain.get_data(user_email, 'access_token')
        access_token_dict = {
            'hasAccessToken':
            bool(access_token),
            'issuedAt':
            str(access_token.get('iat', '')) if bool(access_token) else ''
        }

        self.access_token = json.dumps(access_token_dict)

        return self.access_token
def create_project(user_email: str, user_role: str,
                   **kwargs: Dict[str, Union[bool, str, List[str]]]) -> bool:
    is_user_admin = user_role == 'admin'
    if is_user_admin or \
       cast(List[str], kwargs.get('companies', [])):
        companies = [
            company.lower() for company in kwargs.get('companies', [])
        ]
    else:
        companies = [str(user_domain.get_data(user_email, 'company'))]
    description = str(kwargs.get('description', ''))
    has_forces = kwargs.get('has_forces', False)
    project_name = str(kwargs.get('project_name', '')).lower()
    if kwargs.get('subscription'):
        subscription = str(kwargs.get('subscription'))
    else:
        subscription = 'continuous'
    resp = False
    if not (not description.strip() or not project_name.strip()
            or not all([company.strip()
                        for company in companies]) or not companies):
        if has_forces and subscription != 'continuous':
            # Forces is only available in projects of type continuous
            raise InvalidProjectForcesSubscriptionType()

        if not project_dal.exists(project_name):
            project: ProjectType = {
                'project_name': project_name,
                'description': description,
                'has_forces': has_forces,
                'companies': companies,
                'type': subscription,
                'project_status': 'ACTIVE'
            }
            resp = project_dal.create(project)
            if resp:
                if not is_user_admin:
                    add_user_access = user_domain.update_project_access(
                        user_email, project_name, True)
                    add_user_manager = add_user(project_name.lower(),
                                                user_email.lower(),
                                                'customeradmin')
                    resp = all([add_user_access, add_user_manager])
        else:
            raise InvalidProjectName()
    else:
        raise InvalidParameter()
    return resp
Exemplo n.º 21
0
def get_email_recipients(project_name: str,
                         comment_type: Union[str, bool]) -> List[str]:
    project_users = project_dal.get_users(project_name)
    recipients: List[str] = []

    approvers = FI_MAIL_REVIEWERS.split(',')
    recipients += approvers

    if comment_type == 'observation':
        analysts = [
            user for user in project_users
            if user_domain.get_data(user, 'role') == 'analyst'
        ]
        recipients += analysts
    else:
        recipients += project_users

    return recipients
Exemplo n.º 22
0
def resolve_update_access_token(_, info, expiration_time):
    """Resolve update_access_token mutation."""
    user_info = util.get_jwt_content(info.context)
    email = user_info['user_email']
    token_data = util.calculate_hash_token()
    session_jwt = ''
    success = False

    if util.is_valid_expiration_time(expiration_time):
        session_jwt = jwt.encode(
            {
                'user_email': email,
                'company': user_domain.get_data(
                    email, 'company'),
                'first_name': user_info['first_name'],
                'last_name': user_info['last_name'],
                'jti': token_data['jti'],
                'iat': datetime.utcnow().timestamp(),
                'exp': expiration_time
            },
            algorithm='HS512',
            key=settings.JWT_SECRET_API
        )

        success = user_domain.update_access_token(email, token_data)
        if success:
            util.cloudwatch_log(
                info.context, '{email} update access token'.format(
                    email=user_info['user_email']))
        else:
            util.cloudwatch_log(
                info.context, '{email} attempted to update access token'
                .format(email=user_info['user_email']))
    else:
        util.cloudwatch_log(
            info.context, '{email} attempted to use expiration time \
            greater than six months or minor than current time'
            .format(email=user_info['user_email']))
        raise InvalidExpirationTime()

    return dict(success=success, session_jwt=session_jwt)
Exemplo n.º 23
0
def _get_organization(email, _=None):
    """Get organization."""
    org = user_domain.get_data(email, 'company')
    return dict(organization=org.title())
Exemplo n.º 24
0
def _get_first_login(email, _=None):
    """Get first login."""
    result = user_domain.get_data(email, 'date_joined')
    return dict(first_login=result)
def has_phone_number(email: str) -> str:
    user_info = str(user_domain.get_data(email, 'phone'))
    user_phone = user_info if user_info else '-'
    return user_phone
Exemplo n.º 26
0
def send_comment_mail(comment_data: CommentType,
                      entity_name: str,
                      user_mail: str,
                      comment_type: str = '',
                      entity: Union[str, Dict[str, FindingType], EventType,
                                    ProjectType] = ''):
    parent = comment_data['parent']
    base_url = 'https://fluidattacks.com/integrates/dashboard#!'
    email_context = {
        'user_email': user_mail,
        'comment': str(comment_data['content']).replace('\n', ' '),
        'comment_type': comment_type,
        'parent': parent,
    }
    if entity_name == 'finding':
        finding: Dict[str, FindingType] = cast(Dict[str, FindingType], entity)
        project_name = str(finding.get('projectName', ''))
        recipients = get_email_recipients(project_name, comment_type)

        is_draft = 'releaseDate' in finding
        email_context['finding_id'] = str(finding.get('findingId', ''))
        email_context['finding_name'] = str(finding.get('finding', ''))
        comment_url = (
            base_url +
            '/project/{project}/{finding_type}/{id}/{comment_type}s'.format(
                comment_type=comment_type,
                finding_type='findings' if is_draft else 'drafts',
                id=finding.get('findingId'),
                project=project_name))

    elif entity_name == 'event':
        event = cast(EventType, entity)
        event_id = str(event.get('event_id', ''))
        project_name = str(event.get('project_name', ''))
        recipients = project_dal.get_users(project_name, True)
        email_context['finding_id'] = event_id
        email_context['finding_name'] = f'Event #{event_id}'
        comment_url = ('https://fluidattacks.com/integrates/dashboard#!/'
                       f'project/{project_name}/events/{event_id}/comments')

    elif entity_name == 'project':
        project_name = str(entity)
        recipients = get_email_recipients(project_name, True)
        comment_url = (
            base_url +
            '/project/{project!s}/comments'.format(project=project_name))

    email_context['comment_url'] = comment_url
    email_context['project'] = project_name

    recipients_customers = [
        recipient for recipient in recipients if user_domain.get_data(
            recipient, 'role') in ['customer', 'customeradmin']
    ]
    recipients_not_customers = [
        recipient for recipient in recipients if user_domain.get_data(
            recipient, 'role') not in ['customer', 'customeradmin']
    ]

    email_context_customers = email_context.copy()
    if user_domain.get_data(user_mail,
                            'role') not in ['customer', 'customeradmin']:
        email_context_customers['user_email'] = \
            'Hacker at ' + str(user_domain.get_data(user_mail, 'company')).capitalize()
    email_send_thread = threading.Thread(
        name='New {} email thread'.format(entity_name),
        target=send_mail_comment,
        args=([recipients_not_customers,
               recipients_customers], [email_context,
                                       email_context_customers]))
    email_send_thread.start()
Exemplo n.º 27
0
def _get_remember(jwt_content):
    """Get remember preference."""
    user_email = jwt_content.get('user_email')
    remember = user_domain.get_data(user_email, 'legal_remember')
    result = remember if remember else False
    return dict(remember=result)