Initial commit.
The application can connect to the MariaDB database and Wallix Bastion.
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/target/
|
||||||
|
/.classpath
|
||||||
|
/.mvn/
|
||||||
|
/.settings/
|
||||||
|
/.project
|
||||||
47
pom.xml
Normal file
47
pom.xml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>cm.soungui.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-ext-wallix-sync</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<name>guacamole-ext-wallix-sync</name>
|
||||||
|
<description>Guacamole extension for synchronizing parameters from Wallix Bastion.</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Guacamole Extension API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-ext</artifactId>
|
||||||
|
<version>1.6.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Slf4j API -->
|
||||||
|
<!-- This is needed only if your listener wants to
|
||||||
|
write to the Guacamole web application log -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.7.7</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync;
|
||||||
|
|
||||||
|
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
|
import org.apache.guacamole.properties.LongGuacamoleProperty;
|
||||||
|
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||||
|
|
||||||
|
public class Configuration {
|
||||||
|
|
||||||
|
public static LongGuacamoleProperty UPDATE_INTERVAL = new LongGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "wallix-sync-interval";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty MYSQL_HOSTNAME = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "mysql-hostname";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static IntegerGuacamoleProperty MYSQL_PORT = new IntegerGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "mysql-port";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty MYSQL_DB = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "mysql-database";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty MYSQL_USERNAME = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "mysql-username";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty MYSQL_PASSWORD = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "mysql-password";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty MYSQL_SSL_MODE = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "mysql-ssl-mode";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty WALLIX_URL = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "wallix-url";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty WALLIX_USER = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "wallix-user";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static StringGuacamoleProperty WALLIX_AUTH_KEY = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "wallix-auth-key";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
113
src/main/java/cm/soungui/guacamole/ext/wallix/sync/Wallix.java
Normal file
113
src/main/java/cm/soungui/guacamole/ext/wallix/sync/Wallix.java
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync;
|
||||||
|
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509ExtendedTrustManager;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
public class Wallix {
|
||||||
|
|
||||||
|
private static Wallix INSTANCE;
|
||||||
|
|
||||||
|
private static String HEADER_AUTH_USER = "X-Auth-User";
|
||||||
|
|
||||||
|
private static String HEADER_AUTH_KEY = "X-Auth-Key";
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
private String authKey;
|
||||||
|
|
||||||
|
private Wallix() throws GuacamoleException {
|
||||||
|
Environment environment = LocalEnvironment.getInstance();
|
||||||
|
url = environment.getRequiredProperty(Configuration.WALLIX_URL);
|
||||||
|
user = environment.getRequiredProperty(Configuration.WALLIX_USER);
|
||||||
|
authKey = environment.getRequiredProperty(Configuration.WALLIX_AUTH_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrustManager[] trustAllCerts = new X509ExtendedTrustManager[]{
|
||||||
|
new X509ExtendedTrustManager() {
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new X509Certificate[0]; // Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkClientTrusted(X509Certificate[] certs, String authType) {
|
||||||
|
// Trust all client certificates
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkServerTrusted(X509Certificate[] certs, String authType) {
|
||||||
|
// Trust all server certificates
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(X509Certificate[] arg0, String arg1, Socket arg2)
|
||||||
|
throws CertificateException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(X509Certificate[] arg0, String arg1, SSLEngine arg2)
|
||||||
|
throws CertificateException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(X509Certificate[] arg0, String arg1, Socket arg2)
|
||||||
|
throws CertificateException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(X509Certificate[] arg0, String arg1, SSLEngine arg2)
|
||||||
|
throws CertificateException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Wallix getInstance() throws GuacamoleException {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
INSTANCE = new Wallix();
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String query) throws Exception {
|
||||||
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(url + query))
|
||||||
|
.setHeader(HEADER_AUTH_USER, user)
|
||||||
|
.setHeader(HEADER_AUTH_KEY, authKey)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO Disable this section before release and make this configurable
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, trustAllCerts, new SecureRandom());
|
||||||
|
|
||||||
|
HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
|
||||||
|
try {
|
||||||
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
return response.body();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
import cm.soungui.guacamole.ext.wallix.sync.db.DB;
|
||||||
|
import cm.soungui.guacamole.ext.wallix.sync.db.UserGroup;
|
||||||
|
|
||||||
|
public class WallixConfigSynchronizer implements Runnable {
|
||||||
|
|
||||||
|
private long sleepDuration;
|
||||||
|
private LocalEnvironment environment;
|
||||||
|
|
||||||
|
public WallixConfigSynchronizer() throws GuacamoleException {
|
||||||
|
System.out.println("Wazuh synchronizer Thread started");
|
||||||
|
environment = LocalEnvironment.getInstance();
|
||||||
|
sleepDuration = 1000 * environment.getProperty(Configuration.UPDATE_INTERVAL, Long.valueOf(900));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
System.out.println("Fetching config");
|
||||||
|
synchronizeGroups();
|
||||||
|
Thread.sleep(sleepDuration);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void synchronizeGroups() throws Exception {
|
||||||
|
System.out.println("Synchronizing groups");
|
||||||
|
System.out.println("Getting Wallix groups");
|
||||||
|
printWallixVersion();
|
||||||
|
getWallixGroups();
|
||||||
|
|
||||||
|
DB db = DB.getInstance();
|
||||||
|
List<UserGroup> groups = db.getUserGroups();
|
||||||
|
for (UserGroup group : groups) {
|
||||||
|
System.out.println("ID : " + group.getId() + " - Name : " + group.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printWallixVersion() throws Exception {
|
||||||
|
Wallix wallix = Wallix.getInstance();
|
||||||
|
String output = wallix.get("/version");
|
||||||
|
System.out.println(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getWallixGroups() throws Exception {
|
||||||
|
Wallix wallix = Wallix.getInstance();
|
||||||
|
String output = wallix.get("/usergroups");
|
||||||
|
System.out.println(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync.db;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
import cm.soungui.guacamole.ext.wallix.sync.Configuration;
|
||||||
|
|
||||||
|
public class DB {
|
||||||
|
|
||||||
|
private static DB instance = new DB();
|
||||||
|
|
||||||
|
private Connection mysqlConnection;
|
||||||
|
|
||||||
|
public Connection getMySQLConnection() throws GuacamoleException {
|
||||||
|
try {
|
||||||
|
if (mysqlConnection == null) {
|
||||||
|
Environment environment = LocalEnvironment.getInstance();
|
||||||
|
String hostname = environment.getProperty(Configuration.MYSQL_HOSTNAME, "localhost");
|
||||||
|
int port = environment.getProperty(Configuration.MYSQL_PORT, 3306);
|
||||||
|
String database = environment.getProperty(Configuration.MYSQL_DB, "guacamole_db");
|
||||||
|
String username = environment.getProperty(Configuration.MYSQL_USERNAME);
|
||||||
|
String password = environment.getProperty(Configuration.MYSQL_PASSWORD);
|
||||||
|
String sslMode = environment.getProperty(Configuration.MYSQL_SSL_MODE, "disable");
|
||||||
|
|
||||||
|
String url = new StringBuffer("jdbc:mariadb://")
|
||||||
|
.append(hostname)
|
||||||
|
.append(":").append(port).append("/")
|
||||||
|
.append(database).append("?")
|
||||||
|
.append(username == null ? "" : "user=" + username + "&")
|
||||||
|
.append(password == null ? "" : "password=" + password + "&")
|
||||||
|
.append(sslMode == null ? "" : "sslMode=" + sslMode + "&")
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
System.out.println("JDBC URL : " + url);
|
||||||
|
|
||||||
|
Class.forName("org.mariadb.jdbc.Driver");
|
||||||
|
mysqlConnection = DriverManager.getConnection(url);
|
||||||
|
|
||||||
|
System.out.println("Connected to Database");
|
||||||
|
}
|
||||||
|
|
||||||
|
return mysqlConnection;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new GuacamoleException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DB getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserGroup> getUserGroups() throws GuacamoleException, SQLException {
|
||||||
|
DB db = DB.getInstance();
|
||||||
|
Connection connection = db.getMySQLConnection();
|
||||||
|
ResultSet rs = connection
|
||||||
|
.prepareStatement("select entity_id,name from guacamole_entity where type='USER_GROUP'")
|
||||||
|
.executeQuery();
|
||||||
|
|
||||||
|
ArrayList<UserGroup> groups = new ArrayList<>();
|
||||||
|
while (rs.next()) {
|
||||||
|
UserGroup group = new UserGroup();
|
||||||
|
group.setId(rs.getInt("entity_id"));
|
||||||
|
group.setName(rs.getString("name"));
|
||||||
|
|
||||||
|
groups.add(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync.db;
|
||||||
|
|
||||||
|
public class Entity {
|
||||||
|
|
||||||
|
public static enum EntityType { USER, GROUP };
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public EntityType type;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(EntityType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync.db;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UserGroup extends Entity {
|
||||||
|
|
||||||
|
private int groupId;
|
||||||
|
|
||||||
|
private List<Entity> members = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityType getType() {
|
||||||
|
return EntityType.GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(int groupId) {
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entity> getMembers() {
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package cm.soungui.guacamole.ext.wallix.sync.listener;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.event.ApplicationStartedEvent;
|
||||||
|
import org.apache.guacamole.net.event.listener.Listener;
|
||||||
|
|
||||||
|
import cm.soungui.guacamole.ext.wallix.sync.WallixConfigSynchronizer;
|
||||||
|
|
||||||
|
public class ApplicationStartedListener implements Listener {
|
||||||
|
|
||||||
|
private WallixConfigSynchronizer synchronizer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Object event) throws GuacamoleException {
|
||||||
|
if (event instanceof ApplicationStartedEvent) {
|
||||||
|
synchronizer = new WallixConfigSynchronizer();
|
||||||
|
Thread thread = new Thread(synchronizer);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
src/main/resources/guac-manifest.json
Normal file
12
src/main/resources/guac-manifest.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"guacamoleVersion" : "1.6.0",
|
||||||
|
|
||||||
|
"name" : "Soungui Wallix Synchronizer extension",
|
||||||
|
"namespace" : "soungui-wallix-synchronizer-extension",
|
||||||
|
|
||||||
|
"listeners" : [
|
||||||
|
"cm.soungui.guacamole.ext.wallix.sync.listener.ApplicationStartedListener"
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user