how to use java to query LDAP's ROOTDSE - java

in c#, only two line need to achieve this:
DirectoryEntry rootDSE = new DirectoryEntry(string.Format("LDAP://{0}/RootDSE", dnsDomainName));
string configurationNamingContext = rootDSE.Properties["configurationNamingContext"][0].ToString();
how to do this in java world?

figured it out by using Spring LDAP, the LDAP URL cannot add RootDSE postfix:
LDAP://{domain name}, then use wildcard search:
LdapTemplate template = new LdapTemplate(ldapContextSource);
template.setIgnorePartialResultException(true);
String returnedAtts[] = { "configurationNamingContext" };
SearchControls controls = new SearchControls(SearchControls.OBJECT_SCOPE,0,0,returnedAtts,false,false);
LikeFilter filter = new LikeFilter ("objectClass", "*");
List<String> result = template.search("", filter.encode(), controls, new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("configurationNamingContext").get().toString();
}
});

You can remove some of the extra boilerplate when using the Spring LDAP builder and a Java 8 lambda expression:
List<String> result = ldapTemplate.search(query()
.searchScope(SearchScope.OBJECT)
.where("objectclass").isPresent(),
(AttributesMapper<String>) attrs ->
attrs.get("configurationNamingContext").get().toString());
You'll also need this import:
import static org.springframework.ldap.query.LdapQueryBuilder.*;

Related

Using M2Doc programmatically : Error in the generated .docx document

I'm trying to use M2Doc programmatically, I managed to generate my .docx file without getting errors in the validation part but I'm getting the following Error in the generated document:
{m:self.Name} Couldn't find the 'aqlFeatureAccess(org.eclipse.emf.common.util.URI.Hierarchical,java.lang.String)' service
The "self.Name" part is what I wrote in my template.
I think I'm lacking some kind of reference to a service but I don't know how to fix it.
The self variable is a reference to a model based on a meta-model I created. But I'm not sure I imported it correctly in my code.
I based my code on the code I found on the M2Doc website + some code I found on their GitHub, especially concerning how to add a service in the queryEnvironment.
I searched in the source code of acceleo and M2Doc to see which services they add but it seems that they already import all the services I'm using.
As I said, the validation part is going well and doesn't generate a validation file.
public static void parseDocument(String templateName) throws Exception{
final URI templateURI = URI.createFileURI("Template/"+templateName+"."+M2DocUtils.DOCX_EXTENSION_FILE);
final IQueryEnvironment queryEnvironment =
org.eclipse.acceleo.query.runtime.Query.newEnvironmentWithDefaultServices(null);
final Map<String, String> options = new HashMap<>(); // can be empty
M2DocUtils.prepareEnvironmentServices(queryEnvironment, templateURI, options); // delegate to IServicesConfigurator
prepareEnvironmentServicesCustom(queryEnvironment, options);
final IClassProvider classProvider = new ClassProvider(ClassLoader.getSystemClassLoader()); // use M2DocPlugin.getClassProvider() when running inside Eclipse
try (DocumentTemplate template = M2DocUtils.parse(templateURI, queryEnvironment, classProvider)) {
ValidationMessageLevel validationLevel = validateDocument(template, queryEnvironment, templateName);
if(validationLevel == ValidationMessageLevel.OK){
generateDocument(template, queryEnvironment, templateName, "Model/ComplexKaosModel.kaos");
}
}
}
public static void prepareEnvironmentServicesCustom(IQueryEnvironment queryEnvironment, Map<String, String> options){
Set<IService> services = ServiceUtils.getServices(queryEnvironment, FilterService.class);
ServiceUtils.registerServices(queryEnvironment, services);
M2DocUtils.getConfigurators().forEach((configurator) -> {
ServiceUtils.registerServices(queryEnvironment, configurator.getServices(queryEnvironment, options));
});
}
public static void generateDocument(DocumentTemplate template, IQueryEnvironment queryEnvironment,
String templateName, String modelPath)throws Exception{
final Map<String, Object> variable = new HashMap<>();
variable.put("self", URI.createFileURI(modelPath));
final Monitor monitor = new BasicMonitor.Printing(System.out);
final URI outputURI = URI.createFileURI("Generated/"+templateName+".generated."+M2DocUtils.DOCX_EXTENSION_FILE);
M2DocUtils.generate(template, queryEnvironment, variable, outputURI, monitor);
}
The variable "self" contains an URI:
variable.put("self", URI.createFileURI(modelPath));
You have to load your model and set the value of self to an element from your model using something like:
final ResourceSet rs = new ResourceSetImpl();
final Resource r = rs.getResource(uri, true);
final EObject value = r.getContents()...;
variable.put("self", value);
You can get more details on resource loading in the EMF documentation.

spring boot 2 properties configuration

I have some code that works properly on spring boot prior to 2 and I find it hard to convert it to work with spring boot 2.
Can somebody assist?
public static MutablePropertySources buildPropertySources(String propertyFile, String profile)
{
try
{
Properties properties = new Properties();
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
// load common properties
PropertySource<?> applicationYamlPropertySource = loader.load("properties", new ClassPathResource(propertyFile), null);
Map<String, Object> source = ((MapPropertySource) applicationYamlPropertySource).getSource();
properties.putAll(source);
// load profile properties
if (null != profile)
{
applicationYamlPropertySource = loader.load("properties", new ClassPathResource(propertyFile), profile);
if (null != applicationYamlPropertySource)
{
source = ((MapPropertySource) applicationYamlPropertySource).getSource();
properties.putAll(source);
}
}
propertySources = new MutablePropertySources();
propertySources.addLast(new PropertiesPropertySource("apis", properties));
}
catch (Exception e)
{
log.error("{} file cannot be found.", propertyFile);
return null;
}
}
public static <T> void handleConfigurationProperties(T bean, MutablePropertySources propertySources) throws BindException
{
ConfigurationProperties configurationProperties = bean.getClass().getAnnotation(ConfigurationProperties.class);
if (null != configurationProperties && null != propertySources)
{
String prefix = configurationProperties.prefix();
String value = configurationProperties.value();
if (null == value || value.isEmpty())
{
value = prefix;
}
PropertiesConfigurationFactory<?> configurationFactory = new PropertiesConfigurationFactory<>(bean);
configurationFactory.setPropertySources(propertySources);
configurationFactory.setTargetName(value);
configurationFactory.bindPropertiesToTarget();
}
}
PropertiesConfigurationFactory doesnt exist anymore and the YamlPropertySourceLoader load method no longer accepts 3 parameters.
(the response is not the same either, when I have tried invoking the new method the response objects were wrapped instead of giving me the direct strings/integers etc...)
The PropertiesConfigurationFactory should be replaced with Binder class.
Binder class
Sample code:-
ConfigurationPropertySource source = new MapConfigurationPropertySource(
loadProperties(resource));
Binder binder = new Binder(source);
return binder.bind("initializr", InitializrProperties.class).get();
We were also using PropertiesConfigurationFactory to bind a POJO to a
prefix of the Environment. In 2.0, a brand new Binder API was
introduced that is more flexible and easier to use. Our binding that
took 10 lines of code could be reduced to 3 simple lines.
YamlPropertySourceLoader:-
Yes, this class has been changed in version 2. It doesn't accept the third parameter profile anymore. The method signature has been changed to return List<PropertySource<?>> rather than PropertySource<?>. If you are expecting single source, please get the first occurrence from the list.
Load the resource into one or more property sources. Implementations
may either return a list containing a single source, or in the case of
a multi-document format such as yaml a source for each document in the
resource.
Since there is no accepted answer yet, i post my full solution, which builds upon the answer from #nationquest:
private ConfigClass loadConfiguration(String path){
MutablePropertySources sources = new MutablePropertySources();
Resource res = new FileSystemResource(path);
PropertiesFactoryBean propFactory = new PropertiesFactoryBean();
propFactory.setLocation(res);
propFactory.setSingleton(false);
// resolve potential references to local environment variables
Properties properties = null;
try {
properties = propFactory.getObject();
for(String p : properties.stringPropertyNames()){
properties.setProperty(p, env.resolvePlaceholders(properties.getProperty(p)));
}
} catch (IOException e) {
e.printStackTrace();
}
sources.addLast(new PropertiesPropertySource("prefix", properties));
ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties);
return new Binder(propertySource).bind("prefix", ConfigClass.class).get();
}
The last three lines are the relevant part here.
dirty code but this is how i solved it
https://github.com/mamaorha/easy-wire/tree/master/src/main/java/co/il/nmh/easy/wire/core/utils/properties

Soap Request using axis2 java in Eclipse

I want to make an insert operation in an import set table through the web service from ServiceNow with axis2 version 1.6.4
I used wsdl2java with the wsdl file to create classes in my java project.
After it, i created a new class Request on which i would build my soap request to the webservice.
I believe I have 2 (might be more) major problems:
Unserstanding the difference between a stub and a proxy, respectively, the classes ServiceNowSoapStub and ServiceNowSoapProxy and what is the purpose of each of them.
The existing insert method needs a lot of arguments and i wish to make inserts with a selected number of arguments. do i need to add that specific insert method to the architecture?
Here is what I have:
public class Request {
public static void main(String[] args) throws RemoteException {
try{
HttpTransportProperties.Authenticator basicAuthentication = new HttpTransportProperties.Authenticator();
basicAuthentication.setUsername("xxxx");
basicAuthentication.setPassword("xxxx");
ServiceNowSoapStub proxy = new ServiceNowSoapStub();
proxy._setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, Boolean.FALSE);
proxy._setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, basicAuthentication);
BigDecimal actuals = new BigDecimal("0.04");
BigInteger appId = new BigInteger("3495766");
String appNonApp = "ApNon";
BigInteger productId = new BigInteger("704217");
BigInteger serviceId = new BigInteger("1537");
String serviceName = "IT";
String bpName = "BNK-RSK";
String method = "N";
String bsCode = "ITDV";
String customerCostCode = "30973250";
String customerCountry = "US";
String customerGroup = "Wealth";
String customerLegalEntity = "HB";
String dsId = "EU56";
BigInteger supplierCostCode = new BigInteger("675136");
String supplierCountry = "UK";
String supplierLegalEntity = "BR";
BigInteger total = new BigInteger ("411");
ServiceNowSoapProxy request = new ServiceNowSoapProxy("https://dev34363.service-now.com/u_it_actuals_import_set");
request.insertTest(actuals, appId, appNonApp, productId, serviceId, serviceName, bpName, method, bsCode, customerCostCode,
customerCountry, customerGroup, customerLegalEntity, dsId, supplierCostCode, supplierCountry, supplierLegalEntity, total);
} catch (org.apache.axis.AxisFault e) {
e.printStackTrace();
}
}
}
What am I doing wrong? or can please anyone refer me to some helpful link?
The wiki page of servicenow addressing this subject is a bit out of date so i can't solve my problem through it.
Thanks!

How to incorporate Environments with JClouds-Chef API?

I am using JClouds-Chef to:
Bootstrap a newly-provisioned Linux VM; and then
Run the chef-client on that node to configure it
It's important to note that all I'm currently configuring Chef with is a role (that's all it needs; everything else is set up on the Chef server for me):
public class ChefClient {
public configure() {
String vmIp = "myapp01.example.com";
String vmSshUsername = "myuser";
String vmSshPassword = "12345";
String endpoint = "https://mychefserver.example.com";
String client = "myuser";
String validator = "chef-validator";
String clientCredential = Files.toString(new File("C:\\Users\\myuser\\sandbox\\chef\\myuser.pem"), Charsets.UTF_8);
String validatorCredential = Files.toString(new File("C:\\Users\\myuser\\sandbox\\chef\\chef-validator.pem"), Charsets.UTF_8);
Properties props = new Properties();
props.put(ChefProperties.CHEF_VALIDATOR_NAME, validator);
props.put(ChefProperties.CHEF_VALIDATOR_CREDENTIAL, validatorCredential);
props.put(Constants.PROPERTY_RELAX_HOSTNAME, "true");
props.put(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
ChefContext ctx = ContextBuilder.newBuilder("chef")
.endpoint(endpoint)
.credentials(client, clientCredential)
.overrides(props)
.modules(ImmutableSet.of(new SshjSshClientModule())) //
.buildView(ChefContext.class);
ChefService chef = ctx.getChefService();
List<String> runlist = new RunListBuilder().addRole("platformcontrol_dev").build();
ArrayList<String> runList2 = new ArrayList<String>();
for(String item : runlist) {
runList2.add(item);
}
BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runList2).build();
chef.updateBootstrapConfigForGroup("jclouds-chef", bootstrapConfig);
Statement bootstrap = chef.createBootstrapScriptForGroup("jclouds-chef");
SshClient.Factory sshFactory = ctx.unwrap().utils()
.injector().getInstance(Key.get(new TypeLiteral<SshClient.Factory>() {}));
SshClient ssh = sshFactory.create(HostAndPort.fromParts(vmIp, 22),
LoginCredentials.builder().user(vmSshUsername).password(vmSshPassword).build());
ssh.connect();
try {
StringBuilder rawScript = new StringBuilder();
Map<String, String> resolvedFunctions = ScriptBuilder.resolveFunctionDependenciesForStatements(
new HashMap<String, String>(), ImmutableSet.of(bootstrap), OsFamily.UNIX);
ScriptBuilder.writeFunctions(resolvedFunctions, OsFamily.UNIX, rawScript);
rawScript.append(bootstrap.render(OsFamily.UNIX));
ssh.put("/tmp/chef-bootstrap.sh", rawScript.toString());
ExecResponse result = ssh.exec("bash /tmp/chef-bootstrap.sh");
} catch(Throwable t) {
println "Exception: " + t.message
} finally {
ssh.disconnect();
}
}
}
Our in-house "Chef" (our devops guy) now wants to add the concept of Chef "environments" to all our recipes in addition to the existing roles. This is so that we can specify environment-specific roles for each node. My question: does the JClouds-Chef API handle environments? If so, how might I modify the code to incorporate environment-specific roles?
Is it just as simple as:
BootstrapConfig bootstrapConfig = BootstrapConfig.builder()
.environment("name-of-env-here?").runList(runList2).build();
Yes, it is that simple. That will tell the bootstrap script to register the node in the specified environment.
Take into account, though, that the environment must already exist in the Chef Server. If you want to create nodes in new environments, you can also create them programmatically as follows:
ChefApi api = ctx.unwrapApi(ChefApi.class);
if (api.getEnvironment("environment-name") == null) {
Environment env = Environment.builder()
.name("environment-name")
.description("Some description")
.build();
api.createEnvironment(env);
}

Shiro LDAP Authorization config

Could you please help me with the following situation?
Background information:
I'm using the Vaadin framework.
I'm using the Java security framework Shiro
I'm using ssl.
Authentication works.
Username syntax = pietj#.lcl , jank#.lcl
memberOf field is being used as role.
shiro.ini
[main]
contextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory
contextFactory.url = ldaps://<SERVER>:636
contextFactory.systemUsername = <USERNAME>#<COMPANY>
contextFactory.systemPassword = <PASSWORD>
contextFactory.environment[java.naming.security.protocol] = ssl
realm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
realm.ldapContextFactory = $contextFactory
realm.searchBase = "OU=<APPDIR>,DC=<COMPANY>,DC=lcl"
realm.groupRolesMap = "CN=<ROLE>,OU=<APPDIR>,DC=<COMPANY>,DC=lcl":"Admin"
[roles]
# 'Admin' role has permissions *
Admin = *
Goal
Authorization mapping based on the memberOf field from the currentUser.
Problem
currentUser.hasRole("Admin") always return false.
Questions
Is the above shiro.ini correct?
How do I fix the problem?
I ran into a similar issue using Shiro 1.2.4. Your Shiro configuration is probably OK and the problem lies in ActiveDirectory configuration.
In my setup some users had the userPrincipalName attribute set, while other users hadn't. You can check your in AD server with Sysinternals Active Directory Explorer for example.
This attribute is the one used by Shiro to search for a particular user, then it looks for groups defined in the memberOf attribute.
Take a look at ActiveDirectoryRealm.java source code, method Set<String> getRoleNamesForUser(String username, LdapContext ldapContext) the exact query used is
String searchFilter = "(&(objectClass=*)(userPrincipalName={0}))";
So you have two solutions:
Set userPrincipalName attribute on every user
Change how Shiro searches for users
I went for the second solution. Changing the search query is harder than it should be: you have to customize queryForAuthorizationInfo and getRoleNamesForUser (because its private) methods of ActiveDirectoryRealm class. This is how I did it:
public class CustomActiveDirectoryRealm extends ActiveDirectoryRealm {
#Override
protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals, LdapContextFactory ldapContextFactory) throws NamingException {
String username = (String) getAvailablePrincipal(principals);
// Perform context search
LdapContext ldapContext = ldapContextFactory.getSystemLdapContext();
Set<String> roleNames = null;
try {
roleNames = getRoleNamesForUser(username, ldapContext);
} finally {
LdapUtils.closeContext(ldapContext);
}
return buildAuthorizationInfo(roleNames);
}
// Customize your search query here
private static final String USER_SEARCH_FILTER = "(&(objectClass=*)(sn={0}))";
private Set<String> getRoleNamesForUser(String username, LdapContext ldapContext) throws NamingException {
Set<String> roleNames;
roleNames = new LinkedHashSet<String>();
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String userPrincipalName = username.replace("acegas\\", "");
if (principalSuffix != null) {
userPrincipalName += principalSuffix;
}
Object[] searchArguments = new Object[]{userPrincipalName};
NamingEnumeration answer = ldapContext.search(searchBase, USER_SEARCH_FILTER, searchArguments, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
NamingEnumeration ae = attrs.getAll();
while (ae.hasMore()) {
Attribute attr = (Attribute) ae.next();
if (attr.getID().equals("memberOf")) {
Collection<String> groupNames = LdapUtils.getAllAttributeValues(attr);
Collection<String> rolesForGroups = getRoleNamesForGroups(groupNames);
roleNames.addAll(rolesForGroups);
}
}
}
}
return roleNames;
}
}
And then of course use this class as Realm in shiro.ini
[main]
realm = your.package.CustomActiveDirectoryRealm
realm.ldapContextFactory = $contextFactory
realm.searchBase = "OU=<APPDIR>,DC=<COMPANY>,DC=lcl"
realm.groupRolesMap = "CN=<ROLE>,OU=<APPDIR>,DC=<COMPANY>,DC=lcl":"Admin"

Categories