Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFE] Integration with Identity provider (FreeIPA) #2

Closed
anazmy opened this issue Nov 25, 2016 · 7 comments
Closed

[RFE] Integration with Identity provider (FreeIPA) #2

anazmy opened this issue Nov 25, 2016 · 7 comments
Assignees
Milestone

Comments

@anazmy
Copy link
Contributor

anazmy commented Nov 25, 2016

Relaying on local config file to populate users , their privileges etc.. wont work for big scale environments.

Aker needs to integrate with a central Identity provider - for starters FreeIPA - to :

  • Authenticate users access to Aker servers .
  • Pull list of allowed hosts to the user (HBAC) .
  • Govern the allowed SUDO commands .
@anazmy
Copy link
Contributor Author

anazmy commented Nov 25, 2016

The approach should be like this :

  • Query FreeIPA API for list of hosts .
  • Run Those hosts through HBAC rules - SSH service - for current user .
  • present hosts with at least one successful HBAC rule to the user TUI to access.

@anazmy anazmy self-assigned this Nov 26, 2016
@anazmy
Copy link
Contributor Author

anazmy commented Nov 26, 2016

Since FreeIPA has no property to define "ssh port" for every host , I will relay on a "single" config value to define "ssh port" for all hosts .

@anazmy
Copy link
Contributor Author

anazmy commented Dec 1, 2016

Just a POC

#!/usr/bin/env python

import argparse
import json

from ipalib import api, errors, output, util
from ipalib import Command, Str, Flag, Int
from types import NoneType
from ipalib.cli import to_cli
from ipalib import _, ngettext
from ipapython.dn import DN
from ipalib.plugable import Registry
import pyhbac

def initialize():
    '''
    This function initializes the FreeIPA/IPA API. This function requires
    no arguments. A kerberos key must be present in the users keyring in
    order for this to work.
    '''

    api.bootstrap(context='cli')
    api.finalize()
    try:
        api.Backend.rpcclient.connect()
    except AttributeError:
        api.Backend.xmlclient.connect() #FreeIPA < 4.0 compatibility

    return api

def list_hosts(api):
    '''
    This function prints a list of all hosts. This function requires
    one argument, the FreeIPA/IPA API object.
    '''


    ssh_port = 22
    result = api.Command.host_find()['result']
    members = []
    for host in result:
	    hostname = host['fqdn']
	    if isinstance(hostname, (tuple, list)):
			hostname = hostname[0]
            inventory.append(hostname)
	    #print(hostname)

    return None


def convert_to_ipa_rule(rule):
    # convert a dict with a rule to an pyhbac rule
    ipa_rule = pyhbac.HbacRule(rule['cn'][0])
    ipa_rule.enabled = rule['ipaenabledflag'][0]
    # Following code attempts to process rule systematically
    structure = \
        (('user',       'memberuser',    'user',    'group',        ipa_rule.users),
         ('host',       'memberhost',    'host',    'hostgroup',    ipa_rule.targethosts),
         ('sourcehost', 'sourcehost',    'host',    'hostgroup',    ipa_rule.srchosts),
         ('service',    'memberservice', 'hbacsvc', 'hbacsvcgroup', ipa_rule.services),
        )
    for element in structure:
        category = '%scategory' % (element[0])
        if (category in rule and rule[category][0] == u'all') or (element[0] == 'sourcehost'):
            # rule applies to all elements
            # sourcehost is always set to 'all'
            element[4].category = set([pyhbac.HBAC_CATEGORY_ALL])
        else:
            # rule is about specific entities
            # Check if there are explicitly listed entities
            attr_name = '%s_%s' % (element[1], element[2])
            if attr_name in rule:
                element[4].names = rule[attr_name]
            # Now add groups of entities if they are there
            attr_name = '%s_%s' % (element[1], element[3])
            if attr_name in rule:
                element[4].groups = rule[attr_name]
    if 'externalhost' in rule:
            ipa_rule.srchosts.names.extend(rule['externalhost']) #pylint: disable=E1101
    return ipa_rule
    

def hbactest():
	print "ATTN: Listing allowed hosts"
	user = "power1"
	hbacset = []
	rules = []
	sizelimit = None
	hbacset = api.Command.hbacrule_find(sizelimit=sizelimit)['result']
	for rule in hbacset:
		ipa_rule = convert_to_ipa_rule(rule)
		if ipa_rule.enabled:
			#print ipa_rule.name
			rules.append(ipa_rule)		

	allowed_hosts = []
	for ipa_rule in rules:
		for host in inventory:
			request = pyhbac.HbacRequest()
	
			#Build request user/usergroups
			try:
				request.user.name = user
				search_result = api.Command.user_show(request.user.name)['result']
				groups = search_result['memberof_group']
				if 'memberofindirect_group' in search_result:
					groups += search_result['memberofindirect_group']
				request.user.groups = sorted(set(groups))
			except:
				pass
	
			# Add sshd service + service groups it belongs to
			try:
				request.service.name = "sshd"
				service_result = api.Command.hbacsvc_show(request.service.name)['result']
				if 'memberof_hbacsvcgroup' in service_result:
					request.service.groups = service_result['memberof_hbacsvcgroup']
			except:
				pass	
				
			try:
				request.targethost.name = canonicalize(host)
				tgthost_result = api.Command.host_show(request.targethost.name)['result']
				groups = tgthost_result['memberof_hostgroup']
				if 'memberofindirect_hostgroup' in tgthost_result:
					groups += tgthost_result['memberofindirect_hostgroup']
				request.targethost.groups = sorted(set(groups))                
			except:
				pass
			try:
				res = request.evaluate([ipa_rule])
				if res == pyhbac.HBAC_EVAL_ALLOW:
					print host
			except pyhbac.HbacError as (code, rule_name):
				if code == pyhbac.HBAC_EVAL_ERROR:
					error_rules.append(rule_name)
					print('Native IPA HBAC rule "%s" parsing error: %s' % \
						(rule_name, pyhbac.hbac_result_string(code)))
			except (TypeError, IOError) as (info):
				print('Native IPA HBAC module error: %s' % (info))

	
	
def canonicalize(host):
	"""
	Canonicalize the host name -- add default IPA domain if that is missing
	"""
	if host.find('.') == -1:
		return u'%s.%s' % (host, self.env.domain)
	return host	

if __name__ == '__main__':
    api = initialize()
    inventory = []
    list_hosts(api)
    hbactest()

@anazmy anazmy changed the title [RFE] Integration with Identity provider [RFE] Integration with Identity provider (FreeIPA) Dec 3, 2016
@anazmy
Copy link
Contributor Author

anazmy commented Dec 10, 2016

testing this seems like paramiko is not supporting kerberos using latest gssapi per paramiko/paramiko#584 so I moved strategy a bit to use FreeIPA centralized ssh keys , and it worked fine so far , need some polishing to the code , one gotcha to take in consideration though, aker-gateway server(s) listed in the user ssh allowed hosts, maybe we can remove them via aker config ?

@anazmy anazmy added this to the phase-0 milestone Dec 12, 2016
@anazmy anazmy closed this as completed Dec 19, 2016
@leochan007
Copy link

@anazmy hi there. when run the POC with latest 4.6.0 ipalib.

get this:

Traceback (most recent call last):
File "test.py", line 6, in
from ipalib import api, errors, output, util
File "/usr/lib/python2.7/site-packages/ipalib/init.py", line 919, in
from ipalib import plugable
File "/usr/lib/python2.7/site-packages/ipalib/plugable.py", line 44, in
from ipalib.util import classproperty
File "/usr/lib/python2.7/site-packages/ipalib/util.py", line 59, in
from ipalib.install import sysrestore
ImportError: No module named install

it seems the ipalib's bug...

any suggestions? thx.

@anazmy
Copy link
Contributor Author

anazmy commented Oct 13, 2017

@leochan007 it's not clear what you're trying to do, also I didn't test ipa 4.6 yet.

Can you please report a new issue here with exact details of your setup and debug logging as well if possible.

@leochan007
Copy link

@anazmy 4.5.0 is Ok. i mean the client side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants