I am programming an UI where a user should be able to put in the URL and port to check whether a mongoDB server is running. Furthermore he should be able to provide credentials when necessary.
If the server is not running or the credentials are wrong, I want to provide a message for each case. Similar questions have been answered here:
Check MongoDB authentication with Java 3.0 driver
how to check from a driver, if mongoDB server is running
Unfortunately they use older versions of the Java driver for mongo. I'm using the 3.2+ version of the MongoDB java driver, where i.e. getDB() is deprecated.
My "solution" for the problem looks somewhat like this:
try {
String database = "test";
MongoClient client = null;
if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
MongoCredential credentials = MongoCredential.createCredential(username, database, password.toCharArray());
client = new MongoClient(new ServerAddress(url, Integer.parseInt(port)), Arrays.asList(credentials));
}
else {
client = new MongoClient(url, Integer.parseInt(port));
}
MongoDatabase db = client.getDatabase(database);
db.listCollectionNames().first();
client.close();
return true;
}
catch (MongoCommandException | MongoSecurityException e) {
// program does not get in here when credentials are wrong,
// only when no credentials are provided, but necessary
}
catch (MongoSocketOpenException | MongoTimeoutException e) {
// only get in here after db.listCollectionNames().first() caused a timeout
}
How can I manage to:
Find out when mongoDB server is not running?
Find out that credentials are correct, when necessary?
Edit:
When credentials are wrong (username and/or password) the method catches only the MongoTimeoutException. It's the same when the the wrong URL or port or database is provided. To be clear there are other exceptions printed out, but not caught. Only difference is, when providing no password and no username, even though the database requires them, then the MongoCommandException is caught
Related
I am trying to connect to Hive2 server via JDBC with kerberos authentication. After numerous attempts to make it work, I can't get it to work with the Cloudera driver.
If someone can help me to solve the problem, I can greatly appreciate it.
I have this method:
private Connection establishConnection() {
final String driverPropertyClassName = "driver";
final String urlProperty = "url";
Properties hiveProperties = config.getMatchingProperties("hive.jdbc");
String driverClassName = (String) hiveProperties.remove(driverPropertyClassName);
String url = (String) hiveProperties.remove(urlProperty);
Configuration hadoopConfig = new Configuration();
hadoopConfig.set("hadoop.security.authentication", "Kerberos");
String p = config.getProperty("hadoop.core.site.path");
Path path = new Path(p);
hadoopConfig.addResource(path);
UserGroupInformation.setConfiguration(hadoopConfig);
Connection conn = null;
if (driverClassName != null) {
try {
UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
Driver driver = (Driver) Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection(url, hiveProperties);
} catch (Throwable e) {
LOG.error("Failed to establish Hive connection", e);
}
}
return conn;
}
URL for the server, that I am getting from the properties in the format described in Cloudera documentation
I am getting an exception:
2018-05-05 18:26:49 ERROR HiveReader:147 - Failed to establish Hive connection
java.sql.SQLException: [Cloudera][HiveJDBCDriver](500164) Error initialized or created transport for authentication: Peer indicated failure: Unsupported mechanism type PLAIN.
at com.cloudera.hiveserver2.hivecommon.api.HiveServer2ClientFactory.createTransport(Unknown Source)
at com.cloudera.hiveserver2.hivecommon.api.ZooKeeperEnabledExtendedHS2Factory.createClient(Unknown Source)
...
I thought, that it is missing AuthMech attribute and added AuthMech=1 to the URL. Now I am getting:
java.sql.SQLNonTransientConnectionException: [Cloudera][JDBC](10100) Connection Refused: [Cloudera][JDBC](11640) Required Connection Key(s): KrbHostFQDN, KrbServiceName; [Cloudera][JDBC](11480) Optional Connection Key(s): AsyncExecPollInterval, AutomaticColumnRename, CatalogSchemaSwitch, DecimalColumnScale, DefaultStringColumnLength, DelegationToken, DelegationUID, krbAuthType, KrbRealm, PreparedMetaLimitZero, RowsFetchedPerBlock, SocketTimeOut, ssl, StripCatalogName, transportMode, UseCustomTypeCoercionMap, UseNativeQuery, zk
at com.cloudera.hiveserver2.exceptions.ExceptionConverter.toSQLException(Unknown Source)
at com.cloudera.hiveserver2.jdbc.common.BaseConnectionFactory.checkResponseMap(Unknown Source)
...
But KrbHostFQDN is already specified in the principal property as required in the documentation.
Am I missing something or is this documentation wrong?
Below is the one of the similar kind of problem statement in Impala (just JDBC engine changes others are same) that is resolved by setting "KrbHostFQDN" related properties in JDBC connection string itself.
Try to use the URL below. Hopefully works for u.
String jdbcConnStr = "jdbc:impala://myserver.mycompany.corp:21050/default;SSL=1;AuthMech=1;KrbHostFQDN=myserver.mycompany.corp;KrbRealm=MYCOMPANY.CORP;KrbServiceName=impala"
I suppose that if you are not using SSL=1 but only Kerberos, you just drop that part from the connection string and don't worry about setting up SSL certificates in the java key store, which is yet another hassle.
However in order to get Kerberos to work properly we did the following:
Install MIT Kerberos 4.0.1, which is a kerberos ticket manager. (This is for Windows)
This ticket manager asks you for authentication every time you initiate a connection, creates a ticket and stores it in a kerberos_ticket.dat binary file, whose location can be configured somehow but I do not recall exactly how.
Finally, before launching your JAVA app you have to set an environment variable KRB5CCNAME=C:/path/to/kerberos_ticket.dat. In your java app, you can check that the variable was correctly set by doing System.out.println( "KRB5CCNAME = " + System.getenv( "KRB5CCNAME" ) ). If you are working with eclipse or other IDE you might even have to close the IDE,set up the environment variable and start the IDE again.
NOTE: this last bit is very important, I have observed that if this variable is not properly set up, the connection wont be established...
In Linux, instead MIT Kerberos 4.0.1, there is a program called kinit which does the same thing, although without a graphical interface, which is even more convenient for automation.
I wanted to put it in the comment but it was too long for the comment, therefore I am placing it here:
I tried your suggestion and got another exception:
java.sql.SQLException: [Cloudera]HiveJDBCDriver Error
creating login context using ticket cache: Unable to obtain Principal
Name for authentication .
May be my problem is, that I do not have environment variable KRB5CCNAME set.
I, honestly, never heard about it before.
What is supposed to be in that ticket file.
I do have, however, following line in my main method:
System.setProperty("java.security.krb5.conf", "path/to/krb5.conf");
Which is supposed to be used by
UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
to obtain the kerberos ticket.
To solve this issue update Java Cryptography Extension for the Java version that you use in your system.
Here's the link when you can download JCE for Java 1.7
Uncompress and overwrite those files in $JDK_HOME/jre/lib/security
Restart your computer.
I am trying to connect to an external weblogic embeded LDAP in Oracle ADF.
I've just found a good sample code that uses JpsContextFactory class, it doesnt get any url, username and password. it seems that it connects to local weblogic ldap by defult. I could not figure out how to set a connection to an external weblogic ldap using this class.
the sample code :
private void initIdStoreFactory() {
JpsContextFactory ctxFactory;
try {
ctxFactory = JpsContextFactory.getContextFactory();
JpsContext ctx = ctxFactory.getContext();
LdapIdentityStore idStoreService = (LdapIdentityStore) ctx.getServiceInstance(IdentityStoreService.class);
ldapFactory = idStoreService.getIdmFactory();
storeEnv.put(OIDIdentityStoreFactory.RT_USER_SEARCH_BASES, USER_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_GROUP_SEARCH_BASES, GROUP_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_USER_CREATE_BASES, USER_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_GROUP_CREATE_BASES, GROUP_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_GROUP_SELECTED_CREATE_BASE, GROUP_BASES[0]);
storeEnv.put(OIDIdentityStoreFactory.RT_USER_SELECTED_CREATE_BASE, USER_BASES[0]);
} catch (JpsException e) {
e.printStackTrace();
throw new RuntimeException("Jps Exception encountered", e);
}
}
any suggestion how to use this code to connect to external ldap will be appreciated.
JpsContextFactory is utilised to retrieve the current information of the identity store(s) inside weblogic. In order to use it with an external LDAP, you need first to add a new security provider in Weblogic and declare it as required in order for your application to utilise the new external ldap.
Check this old article of how to do it (http://www.itbuzzpress.com/weblogic-tutorials/securing-oracle-weblogic/configuring-oracle-weblogic-security-providers.html)
I am trying to hook up AWS RDS Aurora database with AWS Lambda Java function. For this, I am yet to see any concrete examples. I have seen some examples but they are non java.
I would also like to configure a mySQL DBMS tool with Aurora which I am not able to do :( Can someone help me with that as well. I have got the connection strings from https://console.aws.amazon.com/rds/home?region=us-east-1#dbinstances.
Also, the code I am trying to connect to DB via Lambda Java is:
private Statement createConnection(Context context) {
logger = context.getLogger();
try {
String url = "jdbc:mysql://HOSTNAME:3306";
String username = "USERNAME";
String password = "PASSWORD";
Connection conn = DriverManager.getConnection(url, username, password);
return conn.createStatement();
} catch (Exception e) {
e.printStackTrace();
logger.log("Caught exception: " + e.getMessage());
}
return null;
}
And yes, this doesn't help as I always get null using the db instance config.
RDS needs be in a security group that opens the DB port to the Security Group attached to the ENI of the lambda.
To enable your Lambda function to access resources inside your private VPC, you must provide additional VPC-specific configuration
information that includes VPC subnet IDs and security group IDs. AWS
Lambda uses this information to set up elastic network interfaces
(ENIs) that enable your function to connect securely to other
resources within your private VPC.
http://docs.aws.amazon.com/lambda/latest/dg/vpc.html
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html
I gave role for DB purp is UserAdmin,I run server with mongod --auth --dbpath c:\mongodb\data\db.
First I done a java file in eclipse to connect DB,it worked properly.
After I create and run the below file in eclipse:
try {
MongoClient mongoClient = new MongoClient("localhost", 27017);
DB db = mongoClient.getDB("purplista");
boolean auth =db.authenticate("purp","123".toCharArray());
System.out.println("Connect to database successfully");
DBCollection doc = db.getCollection("test");
System.out.println("Collection test selected successfully..");
DBCursor cursor = doc.find();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
} catch (Exception e) {
e.printStackTrace();
}
got error like this:
Connect to database successfully..
Collection test selected successfully..
com.mongodb.MongoException: not authorized for query on purplista.test
at
com.mongodb.QueryResultIterator.throwOnQueryFailure(QueryResultIterator.java:214)
at com.mongodb.QueryResultIterator.init(QueryResultIterator.java:198)
at
com.mongodb.QueryResultIterator.initFromQueryResponse(QueryResultIterator.java:176)
at
com.mongodb.QueryResultIterator.(QueryResultIterator.java:64)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:80) at
com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:61) at
com.mongodb.DBCursor._check(DBCursor.java:458) at
com.mongodb.DBCursor._hasNext(DBCursor.java:546) at
com.mongodb.DBCursor.hasNext(DBCursor.java:571) at
purplista.FindDoc.main(FindDoc.java:34)
A couple of issues I see are:
You are not checking the return value of db.authenticate() which may be returning false if it fails to authenticate.
Even if authenticated, you may not have appropriate permissions to perform the intended operations (in your case read) on the specified database.
A few things to check:
Is this a valid user / password - may be try mongo shell using the
same credentials
If valid, does it have appropriate permissions on the database you are using? Since you can create users in "admin" database that can be used to authenticate, however those users may not be setup for additional access that you need for your operations.
If you are using MongoDB v2.6, all the users must be in "admin" database.
You can check for "system.users" collection under the database of interest (test) and admin database to check where the user is setup.
I want access my SharePoint site through Java. I use the SharePoint's webservice, but it needs credentials, and I don't know how to fill in the credentials in Java.
Below is some code in .Net:
WSLists.Lists wslists = new WSLists.Lists();
wslists.Credentials = new System.Net.NetworkCredential("administrator", "pass#word1", "mosing");
Can someone give me some advice or some sample code? Thanks...
The way sharepoint webservices perform actions from java, at least as my team and I found it, is it creates an instance of a webservice, binds a username and password to that instance, then that instance performs an action.
Below you'll see we bind a username and password to a ListSoap object, because we want to checkin or checkout a file. The code below binds the username and password to a port. Then, we can do something like port.checkOut(...). Hope this makes sense for you.
public ListsSoap sharePointListsWebServiceAuth(){
ListsSoap port = null;
if (username != null && password != null) {
try {
ListsService service = new ListsService();
port = service.getListsSoap();
((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
} catch (Exception e) {
System.out.println(e.getMessage());
}
} else {
System.out.println("Couldn't authenticate: Invalid connection details given.");
}
return port;
}
You can use this java api i've developed to communicate with sharepoint rest api. If it still a not full implementation but can solve most common actions you'll need. Also as its open source you can extend it to accomplish what you need.
https://github.com/kikovalle/PLGSharepointRestAPI-java
Hopes this helps