示例#1
0
 def authenticate(self, *args, **kwargs):
     if not all([
             django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID,
             django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
             django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY,
             django_settings.SOCIAL_AUTH_SAML_ORG_INFO,
             django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT,
             django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
             django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS
     ]):
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error(
             "Unable to authenticate, license does not support SAML authentication"
         )
         return None
     created = False
     try:
         user = User.objects.get(username=kwargs.get('username', ''))
         if user and not user.is_in_enterprise_category('saml'):
             return None
     except User.DoesNotExist:
         created = True
     user = super(SAMLAuth, self).authenticate(*args, **kwargs)
     if user and created:
         _decorate_enterprise_user(user, 'saml')
     return user
示例#2
0
def update_user_teams(backend, details, user=None, *args, **kwargs):
    '''
    Update team memberships for the given user based on mapping rules defined
    in settings.
    '''
    if not user:
        return
    from awx.main.models import Organization, Team
    multiple_orgs = feature_enabled('multiple_organizations')
    team_map = backend.setting('TEAM_MAP') or {}
    for team_name, team_opts in team_map.items():

        # Get or create the org to update.  If the license only allows for one
        # org, always use the first active org, unless no org exists.
        if multiple_orgs:
            if 'organization' not in team_opts:
                continue
            org = Organization.objects.get_or_create(name=team_opts['organization'])[0]
        else:
            try:
                org = Organization.objects.order_by('pk')[0]
            except IndexError:
                continue

        # Update team members from expression(s).
        team = Team.objects.get_or_create(name=team_name, organization=org)[0]
        users_expr = team_opts.get('users', None)
        remove = bool(team_opts.get('remove', True))
        _update_m2m_from_expression(user, team.member_role.members, users_expr, remove)
示例#3
0
def update_user_orgs(backend, details, user=None, *args, **kwargs):
    '''
    Update organization memberships for the given user based on mapping rules
    defined in settings.
    '''
    if not user:
        return
    from awx.main.models import Organization
    multiple_orgs = feature_enabled('multiple_organizations')
    org_map = backend.setting('ORGANIZATION_MAP') or {}
    for org_name, org_opts in org_map.items():

        # Get or create the org to update.  If the license only allows for one
        # org, always use the first active org, unless no org exists.
        if multiple_orgs:
            org = Organization.objects.get_or_create(name=org_name)[0]
        else:
            try:
                org = Organization.objects.order_by('pk')[0]
            except IndexError:
                continue

        # Update org admins from expression(s).
        remove = bool(org_opts.get('remove', True))
        admins_expr = org_opts.get('admins', None)
        remove_admins = bool(org_opts.get('remove_admins', remove))
        _update_m2m_from_expression(user, org.admin_role.members, admins_expr, remove_admins)

        # Update org users from expression(s).
        users_expr = org_opts.get('users', None)
        remove_users = bool(org_opts.get('remove_users', remove))
        _update_m2m_from_expression(user, org.member_role.members, users_expr, remove_users)
示例#4
0
文件: backends.py 项目: zuzzas/awx
 def authenticate(self, username, password):
     if not django_settings.RADIUS_SERVER:
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error("Unable to authenticate, license does not support RADIUS authentication")
         return None
     return super(RADIUSBackend, self).authenticate(username, password)
示例#5
0
 def authenticate(self, username, password):
     if not django_settings.TACACSPLUS_HOST:
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error(
             "Unable to authenticate, license does not support TACACS+ authentication"
         )
         return None
     try:
         # Upstream TACACS+ client does not accept non-string, so convert if needed.
         auth = tacacs_plus.TACACSClient(
             django_settings.TACACSPLUS_HOST.encode('utf-8'),
             django_settings.TACACSPLUS_PORT,
             django_settings.TACACSPLUS_SECRET.encode('utf-8'),
             timeout=django_settings.TACACSPLUS_SESSION_TIMEOUT,
         ).authenticate(
             username.encode('utf-8'),
             password.encode('utf-8'),
             authen_type=tacacs_plus.TAC_PLUS_AUTHEN_TYPES[
                 django_settings.TACACSPLUS_AUTH_PROTOCOL],
         )
     except Exception as e:
         logger.exception("TACACS+ Authentication Error: %s" %
                          (e.message, ))
         return None
     if auth.valid:
         return _get_or_set_enterprise_user(username, password, 'tacacs+')
示例#6
0
 def check_permissions(self, request):
     ret = super(WorkflowsEnforcementMixin, self).check_permissions(request)
     if not feature_enabled('workflows') and request.method not in (
             'GET', 'OPTIONS', 'DELETE'):
         raise LicenseForbids(
             _('Your license does not allow use of workflows.'))
     return ret
示例#7
0
    def authenticate(self, username, password):
        if self.settings.START_TLS and ldap.OPT_X_TLS_REQUIRE_CERT in self.settings.CONNECTION_OPTIONS:
            # with python-ldap, if you want to set connection-specific TLS
            # parameters, you must also specify OPT_X_TLS_NEWCTX = 0
            # see: https://stackoverflow.com/a/29722445
            # see: https://stackoverflow.com/a/38136255
            self.settings.CONNECTION_OPTIONS[ldap.OPT_X_TLS_NEWCTX] = 0

        if not self.settings.SERVER_URI:
            return None
        if not feature_enabled('ldap'):
            logger.error(
                "Unable to authenticate, license does not support LDAP authentication"
            )
            return None
        try:
            user = User.objects.get(username=username)
            if user and (not user.profile or not user.profile.ldap_dn):
                return None
        except User.DoesNotExist:
            pass

        try:
            for setting_name, type_ in [
                ('GROUP_SEARCH', 'LDAPSearch'),
                ('GROUP_TYPE', 'LDAPGroupType'),
            ]:
                if getattr(self.settings, setting_name) is None:
                    raise ImproperlyConfigured(
                        "{} must be an {} instance.".format(
                            setting_name, type_))
            return super(LDAPBackend, self).authenticate(username, password)
        except Exception:
            logger.exception("Encountered an error authenticating to LDAP")
            return None
示例#8
0
文件: backends.py 项目: zuzzas/awx
 def get_user(self, user_id):
     if not self.settings.SERVER_URI:
         return None
     if not feature_enabled('ldap'):
         logger.error("Unable to get_user, license does not support LDAP authentication")
         return None
     return super(LDAPBackend, self).get_user(user_id)
示例#9
0
def _update_org_from_attr(user, rel, attr, remove, remove_admins):
    from awx.main.models import Organization
    multiple_orgs = feature_enabled('multiple_organizations')

    org_ids = []

    for org_name in attr:
        if multiple_orgs:
            org = Organization.objects.get_or_create(name=org_name)[0]
        else:
            try:
                org = Organization.objects.order_by('pk')[0]
            except IndexError:
                continue

        org_ids.append(org.id)
        getattr(org, rel).members.add(user)

    if remove:
        [o.member_role.members.remove(user) for o in
            Organization.objects.filter(Q(member_role__members=user) & ~Q(id__in=org_ids))]

    if remove_admins:
        [o.admin_role.members.remove(user) for o in
            Organization.objects.filter(Q(admin_role__members=user) & ~Q(id__in=org_ids))]
示例#10
0
 def check_permissions(self, request):
     ret = super(ActivityStreamEnforcementMixin,
                 self).check_permissions(request)
     if not feature_enabled('activity_streams'):
         raise LicenseForbids(
             _('Your license does not allow use of the activity stream.'))
     return ret
示例#11
0
    def authenticate(self, username, password):
        if self.settings.START_TLS and ldap.OPT_X_TLS_REQUIRE_CERT in self.settings.CONNECTION_OPTIONS:
            # with python-ldap, if you want to set connection-specific TLS
            # parameters, you must also specify OPT_X_TLS_NEWCTX = 0
            # see: https://stackoverflow.com/a/29722445
            # see: https://stackoverflow.com/a/38136255
            self.settings.CONNECTION_OPTIONS[ldap.OPT_X_TLS_NEWCTX] = 0

        if not self.settings.SERVER_URI:
            return None
        if not feature_enabled('ldap'):
            logger.error(
                "Unable to authenticate, license does not support LDAP authentication"
            )
            return None
        try:
            user = User.objects.get(username=username)
            if user and (not user.profile or not user.profile.ldap_dn):
                return None
        except User.DoesNotExist:
            pass
        try:
            return super(LDAPBackend, self).authenticate(username, password)
        except Exception:
            logger.exception("Encountered an error authenticating to LDAP")
            return None
示例#12
0
 def check_permissions(self, request):
     ret = super(SystemTrackingEnforcementMixin,
                 self).check_permissions(request)
     if not feature_enabled('system_tracking'):
         raise LicenseForbids(
             _('Your license does not permit use of system tracking.'))
     return ret
示例#13
0
文件: backends.py 项目: zuzzas/awx
 def get_user(self, user_id):
     if not django_settings.RADIUS_SERVER:
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error("Unable to get_user, license does not support RADIUS authentication")
         return None
     user = super(RADIUSBackend, self).get_user(user_id)
     if not user.has_usable_password():
         return user
示例#14
0
文件: backends.py 项目: zuzzas/awx
 def get_user(self, user_id):
     if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
                 django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, django_settings.SOCIAL_AUTH_SAML_ORG_INFO,
                 django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
                 django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS]):
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error("Unable to get_user, license does not support SAML authentication")
         return None
     return super(SAMLAuth, self).get_user(user_id)
示例#15
0
文件: backends.py 项目: zuzzas/awx
 def get_user(self, user_id):
     if not django_settings.TACACSPLUS_HOST:
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error("Unable to get user, license does not support TACACS+ authentication")
         return None
     try:
         return User.objects.get(pk=user_id)
     except User.DoesNotExist:
         return None
示例#16
0
    def get(self, request, format=None):
        '''Return various sitewide configuration settings'''

        if request.user.is_superuser or request.user.is_system_auditor:
            license_data = get_license(show_key=True)
        else:
            license_data = get_license(show_key=False)
        if not license_data.get('valid_key', False):
            license_data = {}
        if license_data and 'features' in license_data and 'activity_streams' in license_data[
                'features']:
            # FIXME: Make the final setting value dependent on the feature?
            license_data['features'][
                'activity_streams'] &= settings.ACTIVITY_STREAM_ENABLED

        pendo_state = settings.PENDO_TRACKING_STATE if settings.PENDO_TRACKING_STATE in (
            'off', 'anonymous', 'detailed') else 'off'

        data = dict(
            time_zone=settings.TIME_ZONE,
            license_info=license_data,
            version=get_awx_version(),
            ansible_version=get_ansible_version(),
            eula=render_to_string("eula.md") if
            license_data.get('license_type', 'UNLICENSED') != 'open' else '',
            analytics_status=pendo_state,
            become_methods=PRIVILEGE_ESCALATION_METHODS,
        )

        # If LDAP is enabled, user_ldap_fields will return a list of field
        # names that are managed by LDAP and should be read-only for users with
        # a non-empty ldap_dn attribute.
        if getattr(settings, 'AUTH_LDAP_SERVER_URI',
                   None) and feature_enabled('ldap'):
            user_ldap_fields = ['username', 'password']
            user_ldap_fields.extend(
                getattr(settings, 'AUTH_LDAP_USER_ATTR_MAP', {}).keys())
            user_ldap_fields.extend(
                getattr(settings, 'AUTH_LDAP_USER_FLAGS_BY_GROUP', {}).keys())
            data['user_ldap_fields'] = user_ldap_fields

        if request.user.is_superuser \
                or request.user.is_system_auditor \
                or Organization.accessible_objects(request.user, 'admin_role').exists() \
                or Organization.accessible_objects(request.user, 'auditor_role').exists():
            data.update(
                dict(project_base_dir=settings.PROJECTS_ROOT,
                     project_local_paths=Project.get_local_path_choices(),
                     custom_virtualenvs=get_custom_venv_choices()))
        elif JobTemplate.accessible_objects(request.user,
                                            'admin_role').exists():
            data['custom_virtualenvs'] = get_custom_venv_choices()

        return Response(data)
示例#17
0
    def get(self, request, format=None):
        ''' List supported API versions '''

        v1 = reverse('api:api_v1_root_view', kwargs={'version': 'v1'})
        v2 = reverse('api:api_v2_root_view', kwargs={'version': 'v2'})
        data = OrderedDict()
        data['description'] = _('AWX REST API')
        data['current_version'] = v2
        data['available_versions'] = dict(v1=v1, v2=v2)
        data['oauth2'] = drf_reverse('api:oauth_authorization_root_view')
        if feature_enabled('rebranding'):
            data['custom_logo'] = settings.CUSTOM_LOGO
            data['custom_login_info'] = settings.CUSTOM_LOGIN_INFO
        return Response(data)
示例#18
0
文件: backends.py 项目: zuzzas/awx
 def authenticate(self, *args, **kwargs):
     if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
                 django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, django_settings.SOCIAL_AUTH_SAML_ORG_INFO,
                 django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
                 django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS]):
         return None
     if not feature_enabled('enterprise_auth'):
         logger.error("Unable to authenticate, license does not support SAML authentication")
         return None
     user = super(SAMLAuth, self).authenticate(*args, **kwargs)
     # Comes from https://github.com/omab/python-social-auth/blob/v0.2.21/social/backends/base.py#L91
     if getattr(user, 'is_new', False):
         _decorate_enterprise_user(user, 'saml')
     elif user and not user.is_in_enterprise_category('saml'):
         return None
     return user
示例#19
0
    def handle(self, *args, **options):
        if not feature_enabled('system_tracking'):
            raise CommandError("The System Tracking feature is not enabled for your instance")
        cleanup_facts = CleanupFacts()
        if not all([options[GRANULARITY], options[OLDER_THAN]]):
            raise CommandError('Both --granularity and --older_than are required.')

        older_than = self.string_time_to_timestamp(options[OLDER_THAN])
        granularity = self.string_time_to_timestamp(options[GRANULARITY])

        if older_than is None:
            raise CommandError('--older_than invalid value "%s"' % options[OLDER_THAN])
        if granularity is None:
            raise CommandError('--granularity invalid value "%s"' % options[GRANULARITY])

        cleanup_facts.run(older_than, granularity, module=options['module'])
示例#20
0
def update_user_teams_by_saml_attr(backend,
                                   details,
                                   user=None,
                                   *args,
                                   **kwargs):
    if not user:
        return
    from awx.main.models import Organization, Team
    from django.conf import settings
    multiple_orgs = feature_enabled('multiple_organizations')
    team_map = settings.SOCIAL_AUTH_SAML_TEAM_ATTR
    if team_map.get('saml_attr') is None:
        return

    saml_team_names = set(
        kwargs.get('response', {}).get('attributes',
                                       {}).get(team_map['saml_attr'], []))

    team_ids = []
    for team_name_map in team_map.get('team_org_map', []):
        team_name = team_name_map.get('team', '')
        if team_name in saml_team_names:
            if multiple_orgs:
                if not team_name_map.get('organization', ''):
                    # Settings field validation should prevent this.
                    logger.error(
                        "organization name invalid for team {}".format(
                            team_name))
                    continue
                org = Organization.objects.get_or_create(
                    name=team_name_map['organization'])[0]
            else:
                try:
                    org = Organization.objects.order_by('pk')[0]
                except IndexError:
                    continue
            team = Team.objects.get_or_create(name=team_name,
                                              organization=org)[0]

            team_ids.append(team.id)
            team.member_role.members.add(user)

    if team_map.get('remove', True):
        [
            t.member_role.members.remove(user) for t in Team.objects.filter(
                Q(member_role__members=user) & ~Q(id__in=team_ids))
        ]
示例#21
0
 def _default_from_required_settings(self):
     from django.conf import settings
     try:
         backends = settings._awx_conf_settings._get_default('AUTHENTICATION_BACKENDS')
     except AttributeError:
         backends = self.REQUIRED_BACKEND_SETTINGS.keys()
     # Filter which authentication backends are enabled based on their
     # required settings being defined and non-empty. Also filter available
     # backends based on license features.
     for backend, required_settings in self.REQUIRED_BACKEND_SETTINGS.items():
         if backend not in backends:
             continue
         required_feature = self.REQUIRED_BACKEND_FEATURE.get(backend, '')
         if not required_feature or feature_enabled(required_feature):
             if all([getattr(settings, rs, None) for rs in required_settings]):
                 continue
         backends = filter(lambda x: x != backend, backends)
     return backends
示例#22
0
    def create(self, request, *args, **kwargs):
        """Create a new organzation.

        If there is already an organization and the license of this
        instance does not permit multiple organizations, then raise
        LicenseForbids.
        """
        # Sanity check: If the multiple organizations feature is disallowed
        # by the license, then we are only willing to create this organization
        # if no organizations exist in the system.
        if (not feature_enabled('multiple_organizations')
                and self.model.objects.exists()):
            raise LicenseForbids(
                _('Your license only permits a single '
                  'organization to exist.'))

        # Okay, create the organization as usual.
        return super(OrganizationList, self).create(request, *args, **kwargs)
示例#23
0
文件: common.py 项目: benwsapp/awx
def get_external_account(user):
    from django.conf import settings
    from awx.conf.license import feature_enabled
    account_type = None
    if getattr(settings, 'AUTH_LDAP_SERVER_URI', None) and feature_enabled('ldap'):
        try:
            if user.pk and user.profile.ldap_dn and not user.has_usable_password():
                account_type = "ldap"
        except AttributeError:
            pass
    if (getattr(settings, 'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY', None) or
            getattr(settings, 'SOCIAL_AUTH_GITHUB_KEY', None) or
            getattr(settings, 'SOCIAL_AUTH_GITHUB_ORG_KEY', None) or
            getattr(settings, 'SOCIAL_AUTH_GITHUB_TEAM_KEY', None) or
            getattr(settings, 'SOCIAL_AUTH_SAML_ENABLED_IDPS', None)) and user.social_auth.all():
        account_type = "social"
    if (getattr(settings, 'RADIUS_SERVER', None) or
            getattr(settings, 'TACACSPLUS_HOST', None)) and user.enterprise_auth.all():
        account_type = "enterprise"
    return account_type
示例#24
0
def update_user_orgs_by_saml_attr(backend,
                                  details,
                                  user=None,
                                  *args,
                                  **kwargs):
    if not user:
        return
    from awx.main.models import Organization
    from django.conf import settings
    multiple_orgs = feature_enabled('multiple_organizations')
    org_map = settings.SOCIAL_AUTH_SAML_ORGANIZATION_ATTR
    if org_map.get('saml_attr') is None:
        return

    attr_values = kwargs.get('response',
                             {}).get('attributes',
                                     {}).get(org_map['saml_attr'], [])

    org_ids = []

    for org_name in attr_values:
        if multiple_orgs:
            org = Organization.objects.get_or_create(name=org_name)[0]
        else:
            try:
                org = Organization.objects.order_by('pk')[0]
            except IndexError:
                continue

        org_ids.append(org.id)
        org.member_role.members.add(user)

    if org_map.get('remove', True):
        [
            o.member_role.members.remove(user)
            for o in Organization.objects.filter(
                Q(member_role__members=user) & ~Q(id__in=org_ids))
        ]