V4/API Compatiblity
Contents
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 -e force_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
