Closed anazmy closed 7 years ago
The approach should be like this :
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 .
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()
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 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
it seems the ipalib's bug...
any suggestions? thx.
@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.
@anazmy 4.5.0 is Ok. i mean the client side.
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 :