On ke, 12 helmi 2020, White, Daniel E. (GSFC-770.0)[NICS] wrote:
Many thanks for the ansible pointer, Alexander.
As far as API automation, I see two immediate use-cases (and I will file an issue)
1. Some bundled commands for use by IdM admins for user management:
Add a user along with all the necessary additional permissions. These
would use the admin-user's current keytab.
2. Information gathering scripts. Is it possible to set up a
read-only
service keytab for this ?
I want to use Python to be able to capture and process the responses
without all the extra console output of the command line.
Both these requests are already possible with existing Python API.
Since IPA uses GSSAPI for authentication, all standard GSSAPI features
will work just fine:
- automatic acquiring of the credentials using client keytab
(
https://web.mit.edu/kerberos/krb5-latest/doc/basic/keytab_def.html)
- automatic integration with GSS-Proxy for non-root users
(
https://pagure.io/gssproxy/blob/master/f/docs)
Additionally, with FreeIPA 4.7+ you can make services members of groups
which means the groups then can be used to assign
roles/permissions/privileges to Kerberos services to perform any
operations in IPA.
As result, you can create a Kerberos service and grant it needed rights,
then use client keytab for the service principal to authenticate and use
IPA API.
You can play with IPA API using 'ipa console' interactive console. It is
Python interpreter with pre-initialized 'api' object. Normal Python
discovery mechanisms (e.g. using help(foo) and dir(foo)) would work.
Simple example (I'm in admins group here):
$ kinit abokovoy
$ ipa service-add api-requester/`hostname`
-------------------------------------------------
Added service "api-requester/some-host.example.com(a)EXAMPLE.COM"
-------------------------------------------------
Principal name: api-requester/some-host.example.com(a)EXAMPLE.COM
Principal alias: api-requester/some-host.example.com(a)EXAMPLE.COM
Managed by:
some-host.example.com
$ ipa service-allow-retrieve-keytab api-requester/`hostname` --users=abokovoy
Principal name: api-requester/some-host.example.com(a)EXAMPLE.COM
Principal alias: api-requester/some-host.example.com(a)EXAMPLE.COM
Managed by:
some-host.example.com
Users allowed to retrieve keytab: abokovoy
-------------------------
Number of members added 1
$ ipa service-allow-create-keytab api-requester/`hostname` --users=abokovoy
Principal name: api-requester/some-host.example.com(a)EXAMPLE.COM
Principal alias: api-requester/some-host.example.com(a)EXAMPLE.COM
Managed by:
some-host.example.com
Users allowed to retrieve keytab: abokovoy
Users allowed to create keytab: abokovoy
-------------------------
Number of members added 1
-------------------------
$ ipa-getkeytab -Y GSSAPI -k api-requester.keytab -p api-requester/`hostname`
Keytab successfully retrieved and stored in: api-requester.keytab
$ KRB5_CLIENT_KTNAME=./api-requester.keytab KRB5CCNAME=./api.ccache ipa console
(Custom IPA interactive Python console)
api: IPA API object
pp: pretty printer
>> api.Command.whoami()
{'object':
'service', 'command': 'service_show/1', 'arguments':
('api-requester/some-host.example.com(a)EXAMPLE.COM',)}
>>
The latter command (whoami) returns a dictionary describing a requestor
and how to get information about it. This is just to demonstrate that we
are operating under a different identity than my own account.
>>
api.Command.service_show('api-requester/some-host.example.com(a)EXAMPLE.COM')
{'result': {'krbcanonicalname':
('api-requester/some-host.example.com(a)EXAMPLE.COM',), 'krbprincipalname':
('api-requester/some-host.example.com(a)EXAMPLE.COM',), 'has_keytab': True,
'managedby_host': ('some-host.example.com',), 'dn':
'krbprincipalname=api-requester/some-host.example.com(a)EXAMPLE.COM,cn=services,cn=accounts,dc=example,dc=com'},
'value': 'api-requester/some-host.example.com(a)EXAMPLE.COM',
'summary': None}
And on the server side you'll see in httpd's error_log:
ipa: INFO: [jsonserver_kerb] api-requester/some-host.example.com(a)EXAMPLE.COM:
whoami/1(version='2.235'): SUCCESS
ipa: INFO: [jsonserver_kerb] api-requester/some-host.example.com(a)EXAMPLE.COM:
service_show/1('api-requester/some-host.example.com(a)EXAMPLE.COM',
version='2.235'): SUCCESS
Now, if I add
api-requester/some-host.example.com service to a group
that has some roles or privileges associated, this service will be able
to perform permitted actions:
$ kinit abokovoy
$ ipa group-add-member admins --services=api-requester/`hostname`
Group name: admins
Description: Account administrators group
GID: 1792600000
Member users: admin, abokovoy
Member of groups: admin
Member services: api-requester/some-host.example.com(a)EXAMPLE.COM
Member of Sudo rule: admins
-------------------------
Number of members added 1
-------------------------
$ KRB5_CLIENT_KTNAME=./api-requester.keytab KRB5CCNAME=./api.ccache ipa console
(Custom IPA interactive Python console)
api: IPA API object
pp: pretty printer
>> api.Command.host_add('new-host.example.com',
force=True)
{'result': {'krbprincipalname':
('host/new-host.example.com(a)EXAMPLE.COM',), 'fqdn':
('new-host.example.com',), 'objectclass': ('ipaobject',
'nshost', 'ipahost', 'pkiuser', 'ipaservice',
'krbprincipalaux', 'krbprincipal', 'ieee802device',
'ipasshhost', 'top', 'ipaSshGroupOfPubKeys'),
'krbcanonicalname': ('host/new-host.example.com(a)EXAMPLE.COM',),
'ipauniqueid': ('c184ac24-4daf-11ea-9c31-001a4a418612',),
'has_password': False, 'has_keytab': False, 'managedby_host':
('new-host.example.com',), 'dn':
'fqdn=new-host.example.com,cn=computers,cn=accounts,dc=example,dc=com'},
'value': 'new-host.example.com', 'summary': 'Added host
"new-host.example.com"'}
>>
So all you ask for is possible, even more. yes, we lack documentation
around all these actions, this is where your ticket can be helpful.
Please share your experience and whatever findings you'd get out of it.
--
/ Alexander Bokovoy
Sr. Principal Software Engineer
Security / Identity Management Engineering
Red Hat Limited, Finland