API_Compatiblity#
Overview#
The purpose of this feature is to make the IPA CLI tool (IPA client) as simple as possible and develop a way to maintain compatibility among various versions of servers and clients.
Use Cases#
be able to use a new IPA client to run commands on an old IPA server
be able to use an old IPA client to run commands on a new IPA server after incompatible changes were made to the commands
Design#
Backward compatibility with old servers#
Current server code check client version and rejects requests from clients newer than the server. In order to allow the client to talk to old servers, interface definitions for supported old API versions will be bundled with the client.
The client will use interface definition appropriate for the API version on the server - if it has interface definition for the exact API version, it will use that, otherwise it will use the closest lower API version interface definition available.
Interface definitions for the following API versions will be included:
2.49 (RHEL and CentOS 6.5+)
2.114 (Fedora 22)
2.156 (RHEL and CentOS 7.2, Fedora 23)
2.164 (Fedora 24)
When an API version becomes unsupported, its interface definition can be removed from the client.
Additionaly, the client will no longer send argument default values with each request, in order not to trigger an invocation error because of unknown arguments.
Forward compatibility#
Current server is backward compatible with old clients, except when an incompatible change is made to the API. To allow backward incompatible changes in commands, it will be made possible to provide additional versions of a command.
In order to avoid having to deal with API compatibility on a per-version basis in the future, a thin client approach will be used for the client. The server will provide API schema describing commands, their arguments and output fields available over its API. The client will fetch the schema from the server and will dynamically generate and provide the commands to user.
Versioned commands#
The client will use the highest version of command known to it at build time by default, or version 1 for unknown commands. Users will be able to explicitly specify the version of command in each request. The server will use version 1 by default, in order not to break old and 3rd party clients.
Thin client#
Server and client side plugins needs to be split to allow separation.
Module ipalib.plugins
will be split into ipaserver.plugins
and
ipaclient.plugins
.
On the server, API schema will be generated from modules and commands in
ipaserver.plugins
. This schema will be provided to the client.
Documentation for plugins and commands will be part of the schema.
On client, proxy objects of server side plugins will be created using the schema fetched from server. Client will be then able to display command signature and help, perform basic validation of provided arguments (data type check), forward the command call to the server and display returned result. Also client side plugins will be available and usually will preprocess user input, call one or more of server side plugins, and possibly postprocess the result.
Due to security considerations there can’t be executable code in metadata. To allow commands to have arguments with dynamic default values separate server command to retrieve them will be provided.
For the same reason validation of arguments that require normalization or rely on server-side information will be done on the server and clients must send such arguments as plain strings.
When type of an argument is unknown to the client it must be sent as plain string. Server will convert and validate the value.
Caching#
IPA client can cache downloaded API schema to reduce traffic and reduce start up time. IPA client can send fingerprints of known schemata on API initialization. When new API schema is available server will return the full schema. When no new API schema is available server will add warning to the response containing the current API version and schema fingerprint.
API schema fingerprint is calculated on the server and must not change for given schema. Client can’t interpret or calculate the fingerprint.
Implementation#
Backward compatibility with old servers#
The interface definitions for old API versions are bundled in ipaclient.remote_plugins.compat.major_minor Python packages. They look like normal command and object plugin definitions, except they contain no code, only parameter definitions.
Forward compatibility#
Versioned commands#
Command version is specified as part of the command name throughout the
framework, e.g. user-show/1
. If not specified, the default version
is used.
In order to add new versions of a command, use the following pattern:
class MyCommandBase(Command):
# put param definitions common to both versions here
...
@register()
class my_command(MyCommandBase):
# this is the current and main version of the command
version = '2'
...
@register()
class my_command_1(MyCommandBase):
# this is the old compatibility version 1
name = 'my_command'
...
Thin client#
TBD
Caching#
TBD
Feature Management#
UI
Not applicable - UI currently uses json_metadata
API call to
retrieve information about objects, commands and parameters from server.
It’s reflecting current version and changing this is not in a scope of
this design.
CLI
TBD
Configuration#
Client#
TBD
Server#
No new configuration.
Upgrade#
Not applicable - There is no change to the LDAP schema nor the stored data.
How to Use#
Backward compatibility with old servers#
The ipa
command line tool will now work on new clients enrolled
against old server:
client$ rpm -q freeipa-client
freeipa-client-4.4.1-1.fc25.x86_64
client$ ipa ping
------------------------------------------
IPA server version 3.0.0. API version 2.49
------------------------------------------
On clients without this feature, this would fail:
client$ rpm -q freeipa-client
freeipa-client-4.3.2-2.fc24.x86_64
client$ ipa ping
ipa: ERROR: 2.164 client incompatible with 2.49 server at 'https://ipa.example.com/ipa/xml'
Forward compatibility#
Versioned commands#
New client will request the highest available version of a command by default:
client$ ipa -v ping
ipa: INFO: trying https://ipa.example.com/ipa/session/json
ipa: INFO: Forwarding 'ping/1' to server 'https://ipa.example.com/ipa/session/json'
------------------------------------------
IPA server version 4.4.1. API version 2.212
------------------------------------------
It is possible to explicitly request a specific command version instead:
client$ ipa -v ping/1
ipa: INFO: trying https://ipa.example.com/ipa/session/json
ipa: INFO: Forwarding 'ping/1' to server 'https://ipa.example.com/ipa/session/json'
------------------------------------------
IPA server version 4.4.1. API version 2.212
------------------------------------------
Requesting an unknown version of a command will result in an error:
client$ ipa -v ping/2
ipa: INFO: trying https://ipa.example.com/ipa/session/json
ipa: INFO: Forwarding 'ping/2' to server 'https://ipa.example.com/ipa/session/json'
ipa: ERROR: unknown command 'ping/2'
Thin client#
Thin client is transparent to the user, i.e. everything will work the same as on clients without this feature.
It is possible to inspect the API schema using the new API introspection commands:
client$ ipa command-show hostgroup-add
Name: hostgroup_add
Version: 1
Full name: hostgroup_add/1
Documentation: Add a new hostgroup.
Help topic: hostgroup/1
Method of: hostgroup/1
Method name: add
client$ ipa param-find hostgroup-add
Name: cn
Documentation: Name of host-group
Type: str
CLI name: hostgroup_name
Label: Host-group
Convert on server: True
Name: description
Documentation: A description of this host-group
Type: str
Required: False
CLI name: desc
Label: Description
Name: setattr
Documentation: Set an attribute to a name/value pair. Format is attr=value.
For multi-valued attributes, the command replaces the values already present.
Exclude from: webui
Type: str
Required: False
Multi-value: True
CLI name: setattr
Name: addattr
Documentation: Add an attribute/value pair. Format is attr=value. The attribute
must be part of the schema.
Exclude from: webui
Type: str
Required: False
Multi-value: True
CLI name: addattr
Name: all
Documentation: Retrieve and print all attributes from the server. Affects command output.
Exclude from: webui
Type: bool
CLI name: all
Default: False
Positional argument: False
Name: raw
Documentation: Print entries as stored on the server. Only affects output format.
Exclude from: webui
Type: bool
CLI name: raw
Default: False
Positional argument: False
Name: no_members
Documentation: Suppress processing of membership attributes.
Exclude from: webui
Type: bool
Default: False
Positional argument: False
----------------------------
Number of entries returned 7
----------------------------
client$ ipa class-show hostgroup
Name: hostgroup
Version: 1
Full name: hostgroup/1
client$ ipa param-find hostgroup
Name: cn
Documentation: Name of host-group
Type: str
Label: Host-group
Name: description
Documentation: A description of this host-group
Type: str
Required: False
Label: Description
Name: member_host
Type: str
Required: False
Label: Member hosts
Name: member_hostgroup
Type: str
Required: False
Label: Member host-groups
Name: memberof_hostgroup
Type: str
Required: False
Label: Member of host-groups
Name: memberof_netgroup
Type: str
Required: False
Label: Member of netgroups
Name: memberof_sudorule
Type: str
Required: False
Label: Member of Sudo rule
Name: memberof_hbacrule
Type: str
Required: False
Label: Member of HBAC rule
Name: memberindirect_host
Type: str
Required: False
Label: Indirect Member hosts
Name: memberindirect_hostgroup
Type: str
Required: False
Label: Indirect Member host-groups
Name: memberofindirect_hostgroup
Type: str
Required: False
Label: Indirect Member of host-group
Name: memberofindirect_sudorule
Type: str
Required: False
Label: Indirect Member of Sudo rule
Name: memberofindirect_hbacrule
Type: str
Required: False
Label: Indirect Member of HBAC rule
-----------------------------
Number of entries returned 13
-----------------------------
client$ ipa output-find hostgroup-add
Name: summary
Documentation: User-friendly description of action performed
Type: str
Required: False
Name: result
Type: dict
Name: value
Documentation: The primary_key value of the entry, e.g. 'jdoe' for a user
Type: str
----------------------------
Number of entries returned 3
----------------------------
client$ ipa topic-show hostgroup
Name: hostgroup
Version: 1
Full name: hostgroup/1
Documentation: Groups of hosts.
Manage groups of hosts. This is useful for applying access control to a
number of hosts by using Host-based Access Control.
EXAMPLES:
Add a new host group:
ipa hostgroup-add --desc="Baltimore hosts" baltimore
Add another new host group:
ipa hostgroup-add --desc="Maryland hosts" maryland
Add members to the hostgroup (using Bash brace expansion):
ipa hostgroup-add-member --hosts={box1,box2,box3} baltimore
Add a hostgroup as a member of another hostgroup:
ipa hostgroup-add-member --hostgroups=baltimore maryland
Remove a host from the hostgroup:
ipa hostgroup-remove-member --hosts=box2 baltimore
Display a host group:
ipa hostgroup-show baltimore
Delete a hostgroup:
ipa hostgroup-del baltimore
Caching#
API schema is cached on the client for an hour. During this interval, the client will not try to contact the server about the schema:
$ ipa -v ping
ipa: INFO: trying https://ipa.example.com/ipa/session/json
ipa: INFO: Forwarding 'ping/1' to json server 'https://ipa.example.com/ipa/session/json'
-------------------------------------------------------------------
IPA server version 4.4.1. API version 2.212
-------------------------------------------------------------------
To refresh the cache (e.g. if you want the client to immediately use an
up-to-date API schema after server upgrade), use the
force_schema_check
option:
$ ipa -v -eforce_schema_check=1 ping
ipa: INFO: trying https://ipa.example.com/ipa/session/json
ipa: INFO: Forwarding 'schema' to json server 'https://ipa.example.com/ipa/session/json'
ipa: INFO: trying https://ipa.example.com/ipa/session/json
ipa: INFO: Forwarding 'ping/1' to json server 'https://ipa.example.com/ipa/session/json'
-------------------------------------------------------------------
IPA server version 4.4.1. API version 2.212
-------------------------------------------------------------------
Test Plan#
Regression testing#
New IPA client (resp. server) MUST behave exactly the same as the old IPA client (resp. server) when communicating with the old IPA server (resp. client).
Feature testing#
TBD