Working on the ipavault module for ansible-freeipa revealed the issue that vault_add_internal is failing with context="server":
The full traceback is:
File "/tmp/ansible_ipavault_payload_c9v2bouv/ansible_ipavault_payload.zip/ansible/modules/ipavault.py", line 409, in main File "/tmp/ansible_ipavault_payload_c9v2bouv/ansible_ipavault_payload.zip/ansible/module_utils/ansible_freeipa_module.py", line 195, in api_command return api.Command[command](name, **args) File "/usr/lib/python3.6/site-packages/ipalib/frontend.py", line 450, in __call__ return self.__do_call(*args, **options) File "/usr/lib/python3.6/site-packages/ipalib/frontend.py", line 478, in __do_call ret = self.run(*args, **options) File "/usr/lib/python3.6/site-packages/ipalib/frontend.py", line 800, in run return self.execute(*args, **options) File "/usr/lib/python3.6/site-packages/ipaserver/plugins/baseldap.py", line 1190, in execute *keys, **options) File "/usr/lib/python3.6/site-packages/ipaserver/plugins/vault.py", line 788, in pre_callback principal = kerberos.Principal(getattr(context, 'principal'))
It seems that there is no principal defined in the server context. vault_add_internal is properly working with "cli_installer" for example.
Trace back
No trace back
package freeipa-server is not installed package freeipa-client is not installed ipa-server-4.8.0-1.module+el8.1.0+3577+202f0a51.x86_64 ipa-client-4.8.0-1.module+el8.1.0+3577+202f0a51.x86_64 389-ds-base-1.4.1.3-1.module+el8.1.0+3259+a5bc8ad3.x86_64 pki-ca-10.7.1-2.module+el8.1.0+3386+52d02a00.noarch krb5-server-1.17-7.el8.x86_64
IPA vault does not work in server context at all. Large part of the logic is implemented in ipaclient, e.g. key and data wrapping. You must use a client context.
There is a bunch of plugins that implement extra functionality on the client side. The server context should only be used by an API RPC server. Don't use the context == "server" or in_server == True for anything but the API server.
context == "server"
in_server == True
There might be an error that the command can not be used with the server context, but it should not fail this way.
The internal server error needs to be fixed. Also, nothing really prevents vault commands to load the client side API if it needs it. 'server' context is really about running on IPA master and accessing LDAP over LDAPI. The rest should be behaving pretty much the same, only the middleware (wsgi process) is omitted.
# cat ./testrpcclient.console from ipalib import Registry, api register = Registry() if 'in_server' in api.env: from ipalib.rpc import xmlclient, jsonclient register()(xmlclient) register()(jsonclient) # FIXME: api.register only looks at the class name, so we need to create # trivial subclasses with the desired name. if api.env.rpc_protocol == 'xmlrpc': class rpcclient(xmlclient): """xmlclient renamed to 'rpcclient'""" register()(rpcclient) elif api.env.rpc_protocol == 'jsonrpc': class rpcclient(jsonclient): """jsonclient renamed to 'rpcclient'""" register()(rpcclient) else: raise ValueError('unknown rpc_protocol: %s' % api.env.rpc_protocol) api.Backend.rpcclient = rpcclient(api) if not api.Backend.rpcclient.isconnected(): api.Backend.rpcclient.connect() print(api.Backend.rpcclient.forward('ping'))
# ipa -e in_server=true console ./testrpcclient.console {'messages': ({'code': 13001, 'data': {'server_version': '2.234'}, 'message': "API Version number was not sent, forward compatibility not guaranteed. Assuming server's API version, 2.234", 'name': 'VersionMissing', 'type': 'warning'},), 'summary': 'IPA server version 4.9.0.dev201911071622+git4eba78326. API version 2.234'}
So, we can definitely make vault code more robust and actually working in the server mode. The code above is from ipaclient/plugins/rpcclient.py, a bit modified.
ipaclient/plugins/rpcclient.py
There are several plugins that depend on context.principal. The principal is only configured for contexts that have valid GSSAPI credentials.
context.principal
And 'server' context can have valid GSSAPI credentials, as I show above.
The issue here is not lack or presence of the GSSAPI credentials. The problem is that it is rpcclient that configures them in context.principal and not something else. So if you have no rpcclient enabled, you have no context.principal while actual credentials can be in a ccache.
rpcclient
The rpcclient does neither set up context.principal nor use context.principal. There is exactly one place in ipa code base that sets up context.principal outside the current frame. Only the ldap2 backend configures context.principal for use by server-side plugins. The context principal is only set up for GSSAPI bound connections, not auto-bind and not for password-bind.
For password-bind, ldap2 does not configure context.principal. The same is true for LDAPI auto-bind as root.
@cheimes not sure where are you looking. ipalib/rpc.py implements RPCClient class which is exactly a backend for XML-RPC or JSON-RPC clients. It does operate on context.principal: see https://pagure.io/freeipa/blob/master/f/ipalib/rpc.py#_1003 create_connection method.
ipalib/rpc.py
RPCClient
create_connection
This is the code called when you are running a command (derived from ipalib.frontend.Command class) because Command.run() dispatches request to #forward() method if it is not run a server context and default implementation of #forward() performs self.Backend.rpcclient.forward() call, which, in turn, calls create_connection() if needed.
ipalib.frontend.Command
Command.run()
#forward()
server
self.Backend.rpcclient.forward()
create_connection()
So, all we need to do is to make rpcclient available for server context and add logic in the vault code to use it explicitly where needed.
perhaps, it would be good to add a façade that performs lazy loading of the rpcclient so that we don't really load it until it is requested.
Login to comment on this ticket.