[prev in list] [next in list] [prev in thread] [next in thread]
List: forgerock-openidm
Subject: [OpenIDM] using LDAP instead of MySQL
From: Bang.Hong () compuware ! com (Hong, Bang (Vincent))
Date: 2012-11-30 2:19:46
Message-ID: BB59A4D5487F4C4A94E0FB5CA19961E108AF5AA1 () SN2PRD0510MB382 ! namprd05 ! prod ! outlook ! com
[Download RAW message or body]
Hi,
Thank you for you update.
I really have not think about the same configuration on different node. Thank you.
From: openidm-bounces@forgerock.org [mailto:openidm-bounces at forgerock.org] On \
Behalf Of L?szl? Hord?s
Sent: 2012?11?29? 19:25
To: openidm at forgerock.org
Cc: La Joie, Chad
Subject: Re: [OpenIDM] using LDAP instead of MySQL
Hi,
If I understood you correctly you don't want to use MySQL (JDBC Repo Service) at all. \
If it is your intention then you need to fill the hole of /repo service and you need \
to define that router prefix for your custom service. The change will be transparent \
from OpenIDM as long as you can store in LDAP the config, link, audit and user object \
in your LDAP.
See the other answers inline below.
Regards,
Laszlo
On 29 Nov 2012, at 10:50, Hong, Bang (Vincent) wrote:
Thank your update.
I am planning to store configuration in ldap server because of cluster. We want to \
use ldap replication to replicate configuration files. If we are using file and \
memory, we have to make a program to sync those configuration file?
It depends on what is the authoritative source of your configuration. You use OpenIDM \
2.0.3 in a clustered environment and you share the configurations that means all \
server has the same configuration and if you schedule a job all server will pick it \
up and execute it. This issue is addressed in the latest 2.1 version which will be \
released soon.
If you keep the configs in files and you configure all node independently and store \
the configuration in the memory then you don't need to sync anything. You have many \
choices to install the OSGi config objects.
And still there are following things I have not think very clearly
1. In your case, we need develop a LDAPRepoService, and make the ROUTER_PREFIX \
also as repo. If that meaning we need remove openidm-repo-jdbc-2.0.3.jar from \
openidm/bundle/init folder ? because this jar also define ROUTER_PREFIX as repo
Yes, you have to replace it with your custom module.
2. If we have to store configuration in LDAP, if there are one solution to do \
it ?
No, we don't have anything like that.
Thank you
From: openidm-bounces@forgerock.org<mailto:openidm-bounces at forgerock.org> \
[mailto:openidm-bounces at forgerock.org] On Behalf Of L?szl? Hord?s
Sent: 2012?11?29? 17:16
To: openidm at forgerock.org<mailto:openidm at forgerock.org>
Subject: Re: [OpenIDM] using LDAP instead of MySQL
Hi,
We also planning to use OpenDJ as repository for OpenIDM in the close future but \
focusing your questions it should be possible. There are just few questions.
Do you want to store the configuration in LDAP or are you happy to have them in files \
and loaded them to the memory? If Yes then you can implement a simple in memory \
version and get ride of our JDBC and Orient Repo service.
public class Activator implements BundleActivator {
ServiceRegistration<RepoBootService> serviceRegistration = null;
public void start(BundleContext context) throws Exception {
// Register bootstrap repo
Hashtable<String, String> prop = new Hashtable<String, String>();
prop.put(Constants.SERVICE_PID, "org.forgerock.openidm.bootrepo");
prop.put(ServerConstants.ROUTER_PREFIX, "bootrepo");
prop.put("db.type", "MEM");
serviceRegistration =
context.registerService(RepoBootService.class, new BootService(), \
prop); }
public void stop(BundleContext context) throws Exception {
if (null != serviceRegistration) {
serviceRegistration.unregister();
}
}
}
and the BootService is a simple one like:
public class BootService implements RepoBootService {
Logger logger = LoggerFactory.getLogger(BootService.class);
public enum Method {
create, read, update, delete, patch, query, action
}
ConcurrentMap<String, JsonValue> configCacheMap = new ConcurrentHashMap<String, \
JsonValue>();
public JsonValue handle(JsonValue request) throws JsonResourceException {
try {
String id = request.get("id").required().asString();
String rev = request.get("rev").asString();
JsonValue value = request.get("value");
JsonValue params = request.get("params");
JsonValue response = null;
try {
switch (request.get("method").required().asEnum(Method.class)) {
case create:
logger.debug("Call {} method: ID: {}", new Object[] { \
Method.create, id }); if (configCacheMap.containsKey(id)) {
throw new \
JsonResourceException(JsonResourceException.BAD_REQUEST, "Config already exists" + \
id); }
configCacheMap.put(id, value);
response = new JsonValue(new HashMap<String, Object>());
response.put(ServerConstants.OBJECT_PROPERTY_ID, id);
return response;
case read:
logger.debug("Call {} method: ID: {}", new Object[] { \
Method.read, id }); response = configCacheMap.get(id);
if (null == response) {
throw new \
JsonResourceException(JsonResourceException.NOT_FOUND, id); }
return response;
case update:
logger.debug("Call {} method: ID: {}", new Object[] { \
Method.update, id }); response = configCacheMap.get(id);
if (null == response) {
throw new \
JsonResourceException(JsonResourceException.NOT_FOUND, id); }
configCacheMap.put(id, value);
response = new JsonValue(new HashMap<String, Object>());
response.put(ServerConstants.OBJECT_PROPERTY_ID, id);
return response;
case delete:
logger.debug("Call {} method: ID: {}", new Object[] { \
Method.delete, id }); response = configCacheMap.get(id);
if (null == response) {
throw new \
JsonResourceException(JsonResourceException.NOT_FOUND, id); }
configCacheMap.remove(id);
response = new JsonValue(new HashMap<String, Object>());
return response;
case patch:
throw new JsonResourceException(JsonResourceException.FORBIDDEN);
case query:
JsonValue queryId = params.get(QueryConstants.QUERY_ID);
logger.debug("Call {} method: ID: {}, QueryID:", new Object[] { \
Method.query, id, queryId });
if (!queryId.isNull()) {
if (QueryConstants.QUERY_ALL_IDS.equals(queryId.asString())) \
{
response = new JsonValue(new HashMap<String, Object>());
List<Map<String, Object>> result =
new ArrayList<Map<String, \
Object>>(configCacheMap.size());
for (Map.Entry<String, JsonValue> conf : \
configCacheMap.entrySet()) {
Map<String, Object> item = new HashMap<String, \
Object>(2);
item.put(ServerConstants.OBJECT_PROPERTY_ID, \
conf.getKey()); result.add(item);
}
response.put(QueryConstants.QUERY_RESULT, result);
} else {
// Unknown query id
throw new \
JsonResourceException(JsonResourceException.BAD_REQUEST, "Unknown query id: " + \
queryId); }
} else {
throw new \
JsonResourceException(JsonResourceException.BAD_REQUEST,
"Query request does not contain valid query");
}
return response;
case action:
throw new JsonResourceException(JsonResourceException.FORBIDDEN);
default:
throw new \
JsonResourceException(JsonResourceException.BAD_REQUEST); }
} catch (JsonValueException jve) {
throw new JsonResourceException(JsonResourceException.BAD_REQUEST, \
jve); }
} catch (Exception e) {
if (e instanceof JsonResourceException) { // no rethrowing necessary
throw (JsonResourceException) e;
} else { // need to rethrow as resource exception
throw new JsonResourceException(JsonResourceException.INTERNAL_ERROR, \
e); }
}
}
}
If you configure the launcher.json to start your BootService then OpenIDM starts \
without any issue.
{
"location":"bundle",
"includes":[
"**/openidm-system-*.jar"
],
"start-level":1,
"action":"install.start"
},
{
"location":"bundle",
"includes":[
"**/openidm-security-jetty*.jar",
"**/openidm-jetty-fragment*.jar",
"**/openidm-quartz-fragment*.jar",
"**/openidm-config*.jar",
"**/openidm-crypto*.jar"
],
"start-level":2,
"action":"install.start"
},
{
"location":"bundle",
"includes":[
"**/YOUR_CUSTOM_BUNDLE*.jar",
"**/org.apache.felix.scr-*.jar"
],
"start-level":3,
"action":"install.start"
}
Implementing LDAP repo my suggestion would be to implement a class like this:
@Component(name = "org.forgerock.openidm.ldap.repo", policy = \
ConfigurationPolicy.REQUIRE, description = "OpenIDM LDAP repository")
@Service(value = { RepositoryService.class, JsonResource.class })
@Properties({
@Property(name = Constants.SERVICE_VENDOR, value = \
ServerConstants.SERVER_VENDOR_NAME), @Property(name = Constants.SERVICE_DESCRIPTION, \
value = "OpenIDM LDAP Repository"), @Property(name = ServerConstants.ROUTER_PREFIX, \
value = "repo"), @Property(name = "db.type", value = "ldap") })
public class LDAPRepositoryService extends SimpleJsonResource implements \
RepositoryService {
}
There is a simple unit test and you can get the request
import static org.mockito.Mockito.mock;
public class LDAPRepositoryServiceTest {
private LDAPRepositoryService testabel = null;
private ComponentContext context = mock(ComponentContext.class);
private UniversalConnectionPoolManager mgr = null;
@BeforeTest
public void createService() throws Exception {
InputStream inputStream = \
LDAPRepositoryServiceTest.class.getResourceAsStream("/ldap.repo.json"); \
assertNotNull(inputStream); ByteArrayOutputStream buffer = new \
ByteArrayOutputStream(); byte[] temp = new byte[1024];
int read;
while ((read = inputStream.read(temp)) > 0) {
buffer.write(temp, 0, read);
}
String config = new String(buffer.toByteArray());
Dictionary properties = new Hashtable<String, Object>();
properties.put(JSONConfigInstaller.JSON_CONFIG_PROPERTY, config);
//stubbing
when(context.getProperties()).thenReturn(properties);
testabel = new LDAPRepositoryService();
testabel.activate(context);
}
@AfterTest
public void stopService() throws Exception {
testabel.deactivate(context);
}
protected JsonValue loadRequest(String testFile) throws Exception {
InputStream inputStream = \
LDAPRepositoryServiceTest.class.getResourceAsStream(testFile); \
assertNotNull(inputStream); JsonValue request = null;
try {
Map jsonObject = (new ObjectMapper()).readValue(inputStream, Map.class);
request = new JsonValue(jsonObject);
} finally {
inputStream.close();
}
assertNotNull(request);
return request;
}
@Test
public void createUser() throws Exception {
JsonValue request = loadRequest("/request-create-user.json");
JsonValue response = testabel.handle(request);
assertThat(response.required().asMap())
.includes(MapAssert.entry(ServerConstants.OBJECT_PROPERTY_ID, \
"76680e8a-2d5a-4394-885a-6269f1cbccba")); }
You can save the requests into a JSON file when you debugging OpenIDM and replay them \
in the unit test.
I hope this helps to implement your custom LDAP repository.
The Repo audit logger will call your service to save the Log object so I don't think \
you need a custom one but you should be able to implement and configure our service \
to use yours. This was our intend, make it extendable.
Please don't replace the ManagedObjectSet service. It's a fronted before the \
repository service so all /managed/* call is redirected to /repo/managed/*
Regards,
Laszlo
On 29 Nov 2012, at 09:40, Hong, Bang (Vincent) wrote:
Hi all
We are planning to using LDAP instead of Mysql in OpenIDM. My solution is
1. Develop new LDAP schema with objectclass which is similar with mysql schema.
2. Develop a bundle which also implement OpenIDM interface to support CURD to \
instead of ManagedObjectService. 3. Develop another bundle to store user to \
Ldap with standard schema.
But we found something is hard to extension, so far I found following area just like \
hard-coding Audit log: which can config by audit.log, but only CSV and Repository \
supported, we could not extend it.
RepoPersistenceManager: This is for configuration when OSGI start, but it will \
hard-coding to invoke JDBCRepository, We can develop a manager like this one, but I \
could not remove RepoPersistenceManager.
ManagedObjectSet: Since there are one feature for password sync, the password sync \
plug-in will notify openidm with /managed/user and patch method. But if we are using \
Ldap, we have to change it accordingly.
Perhaps my understand is not very experience, but if we can find a way to use LDAP by \
extension and do not modify openidm source coding?
Thank you
Best Regards,
Vincent Hong
_______________________________________________
OpenIDM mailing list
OpenIDM at forgerock.org<mailto:OpenIDM at forgerock.org>
https://lists.forgerock.org/mailman/listinfo/openidm
_______________________________________________
OpenIDM mailing list
OpenIDM at forgerock.org<mailto:OpenIDM at forgerock.org>
https://lists.forgerock.org/mailman/listinfo/openidm
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.forgerock.org/pipermail/openidm/attachments/20121130/ffdfb993/attachment-0001.html \
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic