I'm new to AWS Lambda, We have an already developed application which relies on Spring Data JPA for data access layer. Now in progress of separating individual modules as separate microservices. We are moving on to AWS Lambda. I'm able to see many examples which show how to connect to RDBMS using simple JDBC connection.
How to use Spring Data JPA in AWS Lambda for data access layer?.
Its the same way you would on your traditional servers or container instances (essentially thats all AWS Lambda is a short lived container).
System.out.println("Connecting to database...");
String url = "jdbc:mysql://master.zxxsecygfasd.eu-west-1.rds.amazonaws.com:3306/";
String database = "db_name";
String userName = "root";
String password = "somepass";
try (Connection connection = DriverManager.getConnection(url + database, userName, password)) {
} catch (Exception e) {
System.out.println("Database connection: Failed");
e.printStackTrace();
}
There are however some caveats this will be only able to hit a publicly accessible database from lambda. If you put your Lambda in a specific VPC you are going to need to configure roles for it, security groups and access control.
And finally on the note of JPA there are examples floating out there (Its also pretty standard). I have used hibernate before my personal opinion is that it was a bit heavy.
Related
Hello,
I'm doing a project with the database, where the database is located on Google Cloud. The problem is with multiple connections, where the project should be able to access the database from multiple sources and the cloud enables this originally by manually whitelisting all the IPs, what is unacceptable for my scenario.
I've tried to use SSL, but unfortunately, I'm not able to connect no matter what I do. When I go without SSL, and I whitelist my IP, the connection is successful.
I'm kinda new to databases and on possible ways how to connect to them. Therefore, I need some basic explanation on what should I do or what am I doing wrong, since I'm getting kinda lost.
Things I did following the tutorials from Postgre, Google, websites and already opened threads:
1) Received 3 files from Cloud - server-ca.pem, client-key.pem, client-cert.pem, where I imported server-ca.pem and client-cert.pem into the Java Keystore
2) Tried both ways of naming the properties to connect to the database ( naming them all in URL and setting them as property) where the items are listed from PSQL generated by google cloud
PSQL :
psql "sslmode=verify-ca sslrootcert=server-ca.pem \
sslcert=client-cert.pem sslkey=client-key.pem \
hostaddr=MYIP \
port=5432 \
user=postgres dbname=postgres"
The code:
(.pam files are included in the project directory)
public static Connection connectDb(){
Connection conn = null;
String url = "jdbc:postgresql://MYIP:5432/";
Properties props = new Properties();
props.setProperty("user","postgres");
props.setProperty("password","admin");
props.setProperty("ssl","true");
props.setProperty("sslmode","verify-ca");
props.setProperty("sslrootcert","server-ca.pem");
props.setProperty("sslcert","client-cert.pem");
props.setProperty("sslkey","client-key.pem");
String name = "postgres";
String password = "postgres";
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
}
try {
conn = DriverManager.getConnection(url, props);
} catch (SQLException sqlException){
sqlException.printStackTrace();
}
return conn;
}
Error log:
org.postgresql.util.PSQLException: The connection attempt failed.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:292)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
at org.postgresql.Driver.makeConnection(Driver.java:454)
at org.postgresql.Driver.connect(Driver.java:256)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:678)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:190)
Any tips, help, tutorials, explanation on what should I do, what I did wrong, what kind of approach to choose will help a lot since I've tried all the things and possible ways to solve this problem I've found.
PS: Please, try to use basic and explanatory words and names for stuff, since I worry I might get lost and confused pretty easily. :)
Thanks, Lukas.
I'm running some SQL queries in an AWS Lambda, and was hoping to utilize AWS-XRay's tracing capabilities to get some more detailed information on these calls.
This documentation shows examples of configuration with Spring and Tomcat, but neither of which makes sense to use in my obviously serverless and supposed-to-be lightweight Lambda. Here's how I establish my connections currently:
public Connection getDatabaseConnection(String jdbcUrl, String dbUser, String dbPassword) throws SQLException
{
return DriverManager.getConnection(jdbcUrl, dbUser, dbPassword);
}
try (Connection connection = getDatabaseConnection(getJdbcUrl(), getDbUser(), getDbPassword()))
{
try(ResultSet results = connection.createStatement().executeQuery("SELECT stuff FROM whatever LIMIT 1))
{
return (results.getLong(1));
}
}
Is there any way to utilize AWS-XRay SQL tracing in my use case?
I think one approach would be to use a MySQL statement interceptor:
https://github.com/spullara/mysql-connector-java/blob/master/src/main/java/com/mysql/jdbc/StatementInterceptor.java
You can use AWSXRay.beginSubsegment() in preProcess() method and then AWSXRay.endSubsegment() in the postProcess().
Would be a nice addition to AWS X-Ray SDK for Java which is in open source.
in case you get it working.
For reference of spring based implementation for X-Ray: DataSource based intereceptor
You can use the statementinterceptors property as part of the connection URL to intercept the statement as documented here:
https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html
Update
My teammate pointed out, a newer version of StatementInterceptor is available:
https://github.com/spullara/mysql-connector-java/blob/master/src/main/java/com/mysql/jdbc/StatementInterceptorV2.java
You may want to use that.
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'm trying to create an authenticate database in MongoDB 2.6 using java driver v 2.12.
In particular I need to create a user accessing to admin collection.
Any suggestion?
Thanks.
Here my solution:
MongoClient mcAdmin = new MongoClient(
configuration.getServerAddresses(),
Arrays.asList(MongoCredential.createMongoCRCredential(
MONGODB_ADMIN_USERNAME, "admin",
MONGODB_ADMIN_PASSWORD.toCharArray())));
try {
mcAdmin.setWriteConcern(WriteConcern.JOURNALED);
DB db = mcAdmin.getDB(userDbName);
BasicDBObject commandArguments = new BasicDBObject();
commandArguments.put("user", userUsername);
commandArguments.put("pwd", userPassword);
String[] roles = { "readWrite" };
commandArguments.put("roles", roles);
BasicDBObject command = new BasicDBObject("createUser",
commandArguments);
db.command(command);
} finally {
mcAdmin.close();
}
Doing this in Java code is not the best way to do it, and except for very rare use cases (writing an admin application for MongoDB) even one I would strongly advice against.
Security risk
First of all, your application would need extremely high privileges, namely userAdminAnyDatabase or userAdmin on the admin database, which more or less grants the same rights: creating a superuser at will. To put it in other words: this code would be a high security risk.
Granting roles and rights on a database is an administrative task and for good reasons should be decoupled from an application accessible by arbitrary users.
Technical problems
Activating authentication from a client simply is impossible. The mongod instance in question has to be started with authentication enabled. Furthermore, you would have to save to create a user with the mentioned roles before you could have your app administer users. The problem: you would have to store the password for that user somewhere. Unless you encrypt it, you basically store the most powerful password for your MongoDB databases and cluster in cleartext. And if you encrypt it, you have to pass the key for decryption to your application at some point in a secure manner. And all this to break best practices ("Separation of concerns")?