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