Moving Apache Syncope connectors and resources from one deployment to another
Apache Syncope allows to manage a wide range of IdM concepts like attribute schemas, connectors, resources, mapping, roles, synchronization tasks. Moreover another bunch of new concepts will be supported with 2.0.0 release, like realms.
As reported by project wiki, there is option from exporting the whole configuration from an existing deployment, with purpose of building from scratch another depoyment's configuration. As you can see, Syncope uses a file called content.xml, containing all the initial object configuration: the first time that Syncope initializes with an empty database, all such properties are imported. Unless using an in-memory storage (as H2), such properties are then stored permanently and available for further execution and processing. Subsequent initializations (e.g. container restart) will ignore content.xml.
When you're handling different deployments of Syncope in different environments, like pre-prod and prod, it might be useful to be able to move such configuration back and forth without dropping the internal storage: usage of content.xml is not applicable then. How to migrate configuration items in this case?
In the following we will discuss how to perform this operation.
There are different approaches to deal with this problem: in our experience we have at least two solutions. The former is using the Apache Syncope client library: for example suppose you want to move a resource settings from one instance to another. In this case you can write a simple Maven application having the following dependency (where version needs to match your deployment):
<dependency>
<groupId>org.apache.syncope</groupId>
<artifactId>syncope-client</artifactId>
<version>1.2.5</version>
</dependency>
with the following Java code:
SyncopeClient origClient =
new SyncopeClientFactoryBean().setAddress(ORIG_ADDRESS).create(ADMIN_ID, ADMIN_PWD);
ResourceTO resource =
origClient.getService(ResourceService.class).read(RESOURCE_NAME);
SyncopeClient destClient =
new SyncopeClientFactoryBean().setAddress(DEST_ADDRESS).create(ADMIN_ID, ADMIN_PWD);
destClient.getService(ResourceService.class).update(RESOURCE_NAME, resource)
This assumes that the resource name between the two instances is exactly the same, and also that the underlying connector instance has the same id; if this is not the case, we only need to tweak the ResourceTO object before sending it to the destination system.
If you are pushing resource settings for the first time in the other Syncope installation - instead of update it - you'll have to replace the last line above with:
destClient.getService(ResourceService.class).create(resource);
The second option is to use the CXF web client to access the underlying transport layer in order to manipulate the raw JSON data; the flow is identical to the one above: to GET an item via REST from the origin system and to POST / PUT it again via REST in the destination system.
SyncopeClient origClient =// see above
WebClient sourceWebClient = WebClient.fromClient(WebClient.client(origClient));
sourceWebClient.
accept(MediaType.APPLICATION_JSON_VALUE).
to(ORIG_ADDRESS+””+RESOURCE_NAME, false);
String jsonResource = sourceWebClient.get(String.class);
It is worth to note that getting the resource as JSON string allows to manipulate it in a simpler way: we can save its representation in particular file, change some parameter and re-use this file during import.
Once processing is complete, we can push this resource to the other instance. In case of a new resource, we can proceed with a POST:
String newJsonResource = // e.g. jsonResource obtained above and manipulated
SyncopeClient destClient = // see above
WebClient destWebClient = WebClient.fromClient(WebClient.client(destClient));
destWebClient.
type(MediaType.APPLICATION_JSON_VALUE).
to(DEST_ADDRESS, true).
post(newJsonResource);
In case you want to update an existing resource, you need to perform a PUT operation:
destWebClient.
type(MediaType.APPLICATION_JSON_VALUE).
to(DEST_ADDRESS+””+DEST_RESOURCE_NAME, true).
put(newJsonResource);
Once more, this assumes that resource name is exactly the same, and also that the underlying connector instance has the same id. Otherwise you have to modify during resource processing.
Configuration migration can be done in several ways. In this case we have seen two options: the first one using the Syncope client library only, the second one with CXF Web Client support. The former is useful when you want to process received objects at runtime, while the latter is more general and it's useful when you want to read the entire resource configuration: you can store objects in text files or sent to further processing.
Please also consider that, providing Apache Syncope a full fledged and standard-compliant REST interface, there is no strict need to use any Java library to perform what described above.