Use azure-notificationhubs-java-backend via proxy with authentication - java

Is there a way to use the azure-notificationhubs-java-backend library behind a corporate proxy with authentication?
I will be using the library under an application server (JBoss 6), so I'd like to avoid the classic Java system properties approach (https.proxyHost, https.proxyPort, etc.), since it affects the whole JVM.
Thanks in advance.
Regards,
Nuno Guerreiro

I managed to solve this problem. I'm posting the solution here, just in case anyone needs it ;).
In my specific case, I use a Windows 8 PC and my proxy requires Windows (NTLM) authentication. The code below uses NTLM integrated authentication, i.e., no username and password need to be explicitly set, since the security credentials of the currently logged-on user will be used.
import com.windowsazure.messaging.*;
import java.util.concurrent.Future;
import org.apache.http.auth.AuthSchemeProvider;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.HttpHost;
import org.apache.http.impl.auth.BasicSchemeFactory;
import org.apache.http.impl.auth.DigestSchemeFactory;
import org.apache.http.impl.auth.win.WindowsCredentialsProvider;
import org.apache.http.impl.auth.win.WindowsNTLMSchemeFactory;
import org.apache.http.impl.auth.win.WindowsNegotiateSchemeFactory;
import org.apache.http.impl.client.SystemDefaultCredentialsProvider;
import org.apache.http.impl.client.WinHttpClients;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
public class Test9 {
private static HttpAsyncClientBuilder createAsyncBuilderWithProxy(String proxyHost, int proxyPort) {
if (WinHttpClients.isWinAuthAvailable()) {
final Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
.register(AuthSchemes.BASIC, new BasicSchemeFactory())
.register(AuthSchemes.DIGEST, new DigestSchemeFactory())
.register(AuthSchemes.NTLM, new WindowsNTLMSchemeFactory(null))
.register(AuthSchemes.SPNEGO, new WindowsNegotiateSchemeFactory(null))
.build();
final CredentialsProvider credsProvider = new WindowsCredentialsProvider(new SystemDefaultCredentialsProvider());
return HttpAsyncClientBuilder.create()
.setDefaultCredentialsProvider(credsProvider)
.setDefaultAuthSchemeRegistry(authSchemeRegistry)
.setProxy(new HttpHost(proxyHost, proxyPort));
} else {
return HttpAsyncClientBuilder.create().setProxy(new HttpHost(proxyHost, proxyPort));
}
}
public static void main(String[] args) throws Exception {
if(args.length < 4) {
System.err.println("syntax: java Test9 <hub connection string> <hub name> <push notification address> <push message>");
} else {
String hubConnectionString = args[0];
String hubName = args[1];
String pushNotificationAddress = args[2];
String pushMessage = args[3];
CloseableHttpAsyncClient httpClient = createAsyncBuilderWithProxy("proxy.corporate.com", 8080).build();
httpClient.start();
HttpClientManager.setHttpAsyncClient(httpClient);
NotificationHub hub = new NotificationHub(hubConnectionString, hubName);
Notification notification = Notification.createGcmNotifiation(pushMessage);
hub.sendDirectNotification(notification, pushNotificationAddress);
System.out.println("Notification sent!");
httpClient.close();
}
}
}

Based on the azure-notificationhubs-java-backend library without the proxy setting apis, there seems to be not any way to use it via proxy with authentication without any affection for the whole JVM of your JBoss.
So per my experience, the only way is creating a new instance of JBoss server using Java system properties for proxy settings to run your Azure notificationhubs java backend and communicate with your main application on the other JBoss server instance via the RPC ways like REST API, WS* API, etc.
Hope it helps.

Related

There is unknown field "container" in Tekton

I'm interested in Tekton these days.
However there are some issue when I implement Task with java fabric8.tekton apis.
There exist api which is adding steps in spec in units of container(withContainer) in TaskBuilder class.
However I got error message in rune time like below,
Can I get some advices?
Tekton version - v0.10.1
I used packages like below:
io.fabric8:kubernetes-client:4.7.1
io.fabric8:tekton-client:4.7.1
Here is my complete test code.
package com.example.tekton;
import java.util.ArrayList;
import java.util.List;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerBuilder;
import io.fabric8.kubernetes.client.BaseClient;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.tekton.client.TektonClient;
import io.fabric8.tekton.client.DefaultTektonClient;
import io.fabric8.tekton.client.handlers.TaskHandler;
import io.fabric8.tekton.client.handlers.TaskRunHandler;
import io.fabric8.tekton.pipeline.v1alpha1.ArrayOrString;
import io.fabric8.tekton.pipeline.v1alpha1.Task;
import io.fabric8.tekton.pipeline.v1alpha1.TaskBuilder;
import io.fabric8.tekton.pipeline.v1alpha1.TaskRun;
import io.fabric8.tekton.pipeline.v1alpha1.TaskRunBuilder;
import io.fabric8.tekton.pipeline.v1alpha1.TaskRefBuilder;
public class DefaultKubernetesTest {
public Task getTask() {
Container con = new ContainerBuilder()
.withNewImage("ubuntu")
.withNewName("echo-hello-world")
.addNewCommand("echo")
.addNewArg("hello jinwon world")
.build();
Task task = new TaskBuilder()
.withApiVersion("tekton.dev/v1alpha1")
.withKind("Task")
.withNewMetadata()
.withName("echo-hello-world-test")
.endMetadata()
.withNewSpec()
.addNewStep()
.withContainer(con)
.endStep()
.endSpec()
.build();
return task;
}
public TaskRun getTaskRun() {
TaskRun taskRun = new TaskRunBuilder()
.withNewMetadata()
.withName("taskrun")
.endMetadata()
.withNewSpec()
.withTaskRef(new TaskRefBuilder().withName("echo-hello-world-test").withApiVersion("tekton.dev/v1alpha1").withKind("Task").build())
.endSpec().build();
return taskRun;
}
public static void main(String[] args) {
ConfigBuilder config = new ConfigBuilder();
DefaultKubernetesTest kubeTest = new DefaultKubernetesTest();
String username = "testUser";
String password = "testPwd";
config = config.withMasterUrl("https://192.168.6.236:6443");
config = config.withUsername(username);
config = config.withPassword(password);
Config kubeConfig = config.build();
try (DefaultTektonClient test = new DefaultTektonClient(kubeConfig)) {
Task task = kubeTest.getTask();
TaskRun taskRun = kubeTest.getTaskRun();
test.tasks().inNamespace("test").create(task);
test.taskRuns().inNamespace("test").create(taskRun);
test.close();
}
}
}
Tekton ships with an admission controller, which validates the CRD specs before allowing them into the cluster. Because the project is still in alpha, its moving quite fast. Fabric8 may be templating out K8s objects against a different spec from what has been installed on your cluster. You should be able to validate the spec version used in Fabric8 and remove all the Tekton objects in your cluster and re-apply them at a specific version.

IBM Case Manager Connection

I'm stuck at work for like a week now,
can some1 with CM JavaAPI exprience guide me what am I doing wrong?
I try to connect to the server where the Case Manger is installed and start a
session, maybe I'm doing it all wrong but IBM Knowledge Center did not help.
GOT IT!
package *packacge*;
// jars from the the CM different installation folders on the server
import java.util.List;
import java.util.Locale;
import javax.security.auth.Subject;
import com.filenet.api.core.Connection;
import com.filenet.api.core.ObjectStore;
import com.filenet.api.util.UserContext;
import com.ibm.casemgmt.api.CaseType;
import com.ibm.casemgmt.api.DeployedSolution;
import com.ibm.casemgmt.api.context.CaseMgmtContext;
import com.ibm.casemgmt.api.context.P8ConnectionCache;
import com.ibm.casemgmt.api.context.SimpleP8ConnectionCache;
import com.ibm.casemgmt.api.context.SimpleVWSessionCache;
import com.ibm.casemgmt.api.objectref.ObjectStoreReference;
public class CaseMgmtSession {
public static void main(String[] args) {
P8ConnectionCache connCache = new SimpleP8ConnectionCache();
Connection conn = connCache.getP8Connection("http://*ip of the server CM is installed on*/wsi/FNCEWS40MTOM/");
Subject subject = UserContext.createSubject(conn, *user of CM builder admin*, *pass of CM builder admin*, "FileNetP8WSI");
UserContext uc = UserContext.get();
uc.pushSubject(subject);
Locale origLocale = uc.getLocale();
uc.setLocale(Locale.ENGLISH);
CaseMgmtContext origCmctx = CaseMgmtContext.set(new CaseMgmtContext(new SimpleVWSessionCache(), connCache));
try {
// Code that calls the Case Java API or
// directly calls the CE Java API
// checking the connection is working
ObjectStore os = P8Connector.getObjectStore(*some object store name*);
ObjectStoreReference osRef = new ObjectStoreReference(os);
DeployedSolution someSolution = DeployedSolution.fetchInstance(osRef, *some deployed solution name*);
System.out.println(someSolution.getSolutionName());
List<CaseType> caseTypes = someSolution.getCaseTypes();
for(CaseType ct : caseTypes) {
System.out.println(ct.getName());
}
}
finally {
CaseMgmtContext.set(origCmctx);
uc.setLocale(origLocale);
uc.popSubject();
}
}
}
where P8Connector is a class i wrote that returns an objectstore
I dont know which version of Case Manager you are talking about. However, for 5.2.1.x, you will find ample references on IBM's site. For example - here and here.

List all the user in weblogic by java

Does anyone know how to list all the weblogic users in java?
For instance, there is 5 users in security realm, and I want to get all of them. How do I do?
It's pretty easy. For future reference, if you want to look up something like "how do I do X with weblogic and Java..." use JMX in your google search. Here is an example from weblogic wonders. Note you will need to change your URL and user/password in the code:
import javax.naming.*;
import javax.management.MBeanInfo;
import weblogic.jndi.Environment;
import weblogic.management.runtime.ServerRuntimeMBean;
import weblogic.security.providers.authentication.DefaultAuthenticatorMBean;
import weblogic.management.security.authentication.UserReaderMBean;
import weblogic.management.security.authentication.GroupReaderMBean;
import weblogic.management.MBeanHome;
import weblogic.management.WebLogicMBean;
import weblogic.management.tools.Info;
import weblogic.management.Helper;
import weblogic.management.security.authentication.*;
public class ListUsersAndGroups
{
public static void main(String[] args)
{
MBeanHome home = null;
try
{
Environment env = new Environment();
env.setProviderUrl(“t3://localhost:7001?);
env.setSecurityPrincipal(“weblogic”);
env.setSecurityCredentials(“weblogic”);
Context ctx = env.getInitialContext();
home = (MBeanHome)ctx.lookup(“weblogic.management.adminhome”);
weblogic.management.security.RealmMBean rmBean =
home.getActiveDomain().getSecurityConfiguration().getDefaultRealm();
AuthenticationProviderMBean[] authenticationBeans =
rmBean.getAuthenticationProviders();
DefaultAuthenticatorMBean defaultAuthenticationMBean =
(DefaultAuthenticatorMBean)authenticationBeans[0];
UserReaderMBean userReaderMBean =
(UserReaderMBean)defaultAuthenticationMBean;
String userCurName = userReaderMBean.listUsers(“*”, 100);
while (userReaderMBean.haveCurrent(userCurName) )
{
String user = userReaderMBean.getCurrentName(userCurName);
System.out.println(“\n User: ” + user);
userReaderMBean.advance(userCurName);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
EDIT
There isn't really any way around have to know the user/password to look up the users. You can do it via WLST scripting as well if that sounds like a better option. See an example here.
Last but not least, you could set anonymous bind on the embedded ldap for Weblogic to allow anonymous lookups (which is generally not recommended for production). This sample shows how to do it with an external client: Weblogic w/External Ldap Client
The key settings are:
Your Domain -> Security -> Embedded LDAP
Change the (default generated) password (for example: weblogic)
Enable “Anonymous Bind Allowed”

Using NTLM authentication in Java applications

I want to use Windows NTLM authentication in my Java application to authenticate intranet users transparently. The users should not notice any authentication if using their browsers (single sign-on).
I've found a few libs with NTLM support, but don't know which one to use:
http://spnego.sourceforge.net/
http://sourceforge.net/projects/ntlmv2auth/
http://jcifs.samba.org/
http://www.ioplex.com/jespa.html
http://www.luigidragone.com/software/ntlm-authentication-in-java/
Any suggestions where to start?
Out of the above list, only ntlmv2-auth and Jespa support NTLMv2. Jespa is workable but commercial. ntlmv2-auth I haven't tried but it's based on the code from Liferay, which I've seen working before.
'ntlm-authentication-in-java' is only NTLMv1, which is old, insecure, and works in a dwindling number of environments as people upgrade to newer Windows versions. JCIFS used to have an NTLMv1 HTTP auth filter, but it was removed in later versions, as the way it was implemented amounts to a man-in-the-middle attack on the insecure protocol. (The same appears to be true of 'ntlm-authentication-in-java'.)
The 'spnego' project is Kerberos not NTLM. If you want to replicate full IWA as IIS does it, you'd need to support both NTLMv2 and Kerberos ('NTLM' auth, 'Negotiate' auth, NTLMSSP-in-SPNego auth and NTLM-masquerading-as-Negotiate auth).
Luigi Dragone's script is really old and seems to always fail.
HttpURLConnection can work with NTLM if you add library jcifs, this example works with latest jcifs-1.3.18 :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.impl.auth.NTLMEngineException;
public class TestNTLMConnection {
public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException {
// Method 1 : authentication in URL
jcifs.Config.registerSmbURLHandler();
URL urlRequest = new URL("http://domain%5Cuser:pass#127.0.0.1/");
// or Method 2 : authentication via System.setProperty()
// System.setProperty("http.auth.ntlm.domain", "domain");
// System.setProperty("jcifs.smb.client.domain", "domain");
// System.setProperty("jcifs.smb.client.username", "user");
// System.setProperty("jcifs.smb.client.password", "pass");
// Not verified // System.setProperty("jcifs.netbios.hostname", "host");
// System.setProperty("java.protocol.handler.pkgs", "jcifs");
// URL urlRequest = new URL("http://127.0.0.1:8180/simulate_get.php");
HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection();
StringBuilder response = new StringBuilder();
try {
InputStream stream = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String str = "";
while ((str = in.readLine()) != null) {
response.append(str);
}
in.close();
System.out.println(response);
} catch(IOException err) {
System.out.println(err);
} finally {
Map<String, String> msgResponse = new HashMap<String, String>();
for (int i = 0;; i++) {
String headerName = conn.getHeaderFieldKey(i);
String headerValue = conn.getHeaderField(i);
if (headerName == null && headerValue == null) {
break;
}
msgResponse.put(headerName == null ? "Method" : headerName, headerValue);
}
System.out.println(msgResponse);
}
}
}
And if you are curious about the content of each handshake, you can find another example using jcifs and Socket on this thread.
Had to recently implement this at work hence here is updated solution with Spring's RestTemplate:
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
public class Runner {
public static void main(String[] args) {
var credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new NTCredentials("username", "password", "", "someDomain"));
try (var client = HttpClients.custom()
.setDefaultCredentialsProvider(credentialsProvider)
.build();) {
var requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(client);
RestTemplate restTemplate = new RestTemplate(requestFactory);
ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("url", new HttpEntity<>("yourDtoObject"), String.class);
} catch (IOException e) {
e.printStackTrace();
}
}
}
dependencies needed are: spring-web and org.apache.httpcomponents
ps: it is important to enter username without domain otherwise it doesn't work. As in if your domain is companyName/username often people just enter that whole thing as username and what you should do is enter them separately where domain="companyName" and username="username"
Ref: https://jcifs.samba.org/src/docs/faq.html#ntlmv2
Q: Does jCIFS support NTLMv2?
A: Yes. As of 1.3.0, JCIFS fully supports NTLMv2 and uses it by default.
Note: The NTLM HTTP SSO Filter that used to be included with JCIFS cannot support NTLMv2.
Relatively from the list you gave,I would go with JCIFS.
The library is mature , and their documentation is good.
To top it off they had fairly regular releases , and the last one being Nov 2011.
Personal Experience : it was fairly easy to get started when compared to others i have tried (spnego and ntmv2auth)

How to connect to an mBeanServer in another local process?

If you set the "com.sun.management.jmxremote" system property when you start a JVM, you can run jconsole or visualvm and connect to that local mBeanServer. I want to do the same thing they are doing but can't figure out how.
Is there a service URL you can use to identify a locally running JVM?
I know I could do this by setting up a jmxmp or rmi listener on a specific port and then connecting to that port, but I don't want to do that because it means I have to manage the ports and know which port goes to which jvm (we run multiple jvms on the same server).
Thanks to Nicholas and Scott for the post and discussion. Was able to piece this together based on that info and some trial and error.
Sharing so others don't have to do the same leg work. This will attach to a JVM and get its memory usage.
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.sun.tools.attach.spi.AttachProvider;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class AttachFun {
public static void main(String[] args) throws Exception {
final AttachProvider attachProvider = AttachProvider.providers().get(0);
VirtualMachineDescriptor descriptor = null;
for (VirtualMachineDescriptor virtualMachineDescriptor : attachProvider.listVirtualMachines()) {
if (pickThisOne(virtualMachineDescriptor)) {
descriptor = virtualMachineDescriptor;
break;
}
}
if (descriptor == null) throw new RuntimeException("You didn't pick one");
final VirtualMachine virtualMachine = attachProvider.attachVirtualMachine(descriptor);
virtualMachine.loadAgent("/System/Library/Frameworks/JavaVM.framework/Home/lib/management-agent.jar", "com.sun.management.jmxremote");
final Object portObject = virtualMachine.getAgentProperties().get("com.sun.management.jmxremote.localConnectorAddress");
final JMXServiceURL target = new JMXServiceURL(portObject + "");
final JMXConnector connector = JMXConnectorFactory.connect(target);
final MBeanServerConnection remote = connector.getMBeanServerConnection();
final ObjectName memory = new ObjectName("java.lang:type=Memory");
CompositeData cd = (CompositeData) remote.getAttribute(memory, "HeapMemoryUsage");
final Long used = (Long) cd.get("used");
System.out.println(used);
}
private static boolean pickThisOne(VirtualMachineDescriptor virtualMachineDescriptor) {
// TODO
return false;
}
}
You need the Attach API. It will locate running [Attach API capable] JVMs on the same host and return meta-data on each as well as enable a JMXConnector. It's basically what you see when you start JConsole and the connect menu displays running JVMs, including Java 1.6+ instances that were not started with any special JMX command line directives.
//Nicholas

Categories

Resources