DIRKRB-673 Add REST API for Kerby KDC configuration.
diff --git a/has-project/has-server/pom.xml b/has-project/has-server/pom.xml
index 624c464..8d762a8 100644
--- a/has-project/has-server/pom.xml
+++ b/has-project/has-server/pom.xml
@@ -64,6 +64,16 @@
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
+ <groupId>commons-dbutils</groupId>
+ <artifactId>commons-dbutils</artifactId>
+ <version>${commons-dbutils.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.drizzle.jdbc</groupId>
+ <artifactId>drizzle-jdbc</artifactId>
+ <version>${drizzle-jdbc.version}</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java
index 121c7ca..5937782 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/HasServer.java
@@ -19,6 +19,7 @@
*/
package org.apache.kerby.has.server;
+import org.apache.commons.dbutils.DbUtils;
import org.apache.hadoop.http.HttpConfig;
import org.apache.kerby.has.common.HasConfig;
import org.apache.kerby.has.common.HasException;
@@ -32,15 +33,31 @@
import org.apache.kerby.kerberos.kerb.client.ClientUtil;
import org.apache.kerby.kerberos.kerb.client.KrbConfig;
import org.apache.kerby.kerberos.kerb.client.KrbSetting;
+import org.apache.kerby.kerberos.kerb.identity.backend.BackendConfig;
import org.apache.kerby.kerberos.kerb.identity.backend.IdentityBackend;
import org.apache.kerby.kerberos.kerb.server.KdcServer;
+import org.apache.kerby.kerberos.kerb.server.KdcUtil;
+import org.apache.kerby.util.IOUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
/**
* The HAS KDC server implementation.
@@ -103,6 +120,16 @@
}
public void startKdcServer() throws HasException {
+ BackendConfig backendConfig;
+ try {
+ backendConfig = KdcUtil.getBackendConfig(getConfDir());
+ } catch (KrbException e) {
+ throw new HasException("Failed to get backend config. " + e);
+ }
+ String backendJar = backendConfig.getString("kdc_identity_backend");
+ if (backendJar.equals("org.apache.kerby.has.server.kdc.MySQLIdentityBackend")) {
+ updateKdcConf();
+ }
try {
kdcServer = new KdcServer(confDir);
} catch (KrbException e) {
@@ -208,6 +235,340 @@
return nameString;
}
+ /**
+ * Update conf file.
+ *
+ * @param confName conf file name
+ * @param values customized values
+ * @throws IOException throw IOException
+ * @throws KrbException e
+ */
+ public void updateConfFile(String confName, Map<String, String> values)
+ throws IOException, HasException {
+ File confFile = new File(getConfDir().getAbsolutePath(), confName);
+ if (confFile.exists()) {
+ // Update conf file content
+ InputStream templateResource;
+ if (confName.equals("has-server.conf")) {
+ templateResource = new FileInputStream(confFile);
+ } else {
+ String resourcePath = "/" + confName + ".template";
+ templateResource = getClass().getResourceAsStream(resourcePath);
+ }
+ String content = IOUtil.readInput(templateResource);
+ for (Map.Entry<String, String> entry : values.entrySet()) {
+ content = content.replaceAll(Pattern.quote(entry.getKey()), entry.getValue());
+ }
+
+ // Delete the original conf file
+ boolean delete = confFile.delete();
+ if (!delete) {
+ throw new HasException("Failed to delete conf file: " + confName);
+ }
+
+ // Save the updated conf file
+ IOUtil.writeFile(content, confFile);
+ } else {
+ throw new HasException("Conf file: " + confName + " not found.");
+ }
+ }
+
+ /**
+ * Get KDC Config from MySQL.
+ *
+ * @return Kdc config
+ * @throws KrbException e
+ */
+ private Map<String, String> getKdcConf() throws HasException {
+ PreparedStatement preStm = null;
+ ResultSet result = null;
+ Map<String, String> kdcConf = new HashMap<>();
+ BackendConfig backendConfig;
+ try {
+ backendConfig = KdcUtil.getBackendConfig(getConfDir());
+ } catch (KrbException e) {
+ throw new HasException("Getting backend config failed." + e.getMessage());
+ }
+ String driver = backendConfig.getString("mysql_driver");
+ String url = backendConfig.getString("mysql_url");
+ String user = backendConfig.getString("mysql_user");
+ String password = backendConfig.getString("mysql_password");
+ Connection connection = startConnection(driver, url, user, password);
+ try {
+
+ // Get Kdc configuration from kdc_config table
+ String stmKdc = "SELECT * FROM `kdc_config` WHERE id = 1";
+ preStm = connection.prepareStatement(stmKdc);
+ result = preStm.executeQuery();
+ while (result.next()) {
+ String realm = result.getString("realm");
+ String servers = result.getString("servers");
+ String port = String.valueOf(result.getInt("port"));
+ kdcConf.put("servers", servers);
+ kdcConf.put("_PORT_", port);
+ kdcConf.put("_REALM_", realm);
+ }
+
+ } catch (SQLException e) {
+ LOG.error("Error occurred while getting kdc config.");
+ throw new HasException("Failed to get kdc config. ", e);
+ } finally {
+ DbUtils.closeQuietly(preStm);
+ DbUtils.closeQuietly(result);
+ DbUtils.closeQuietly(connection);
+ }
+
+ return kdcConf;
+ }
+
+ /**
+ * Update KDC conf file.
+ *
+ * @throws KrbException e
+ */
+ private void updateKdcConf() throws HasException {
+ try {
+ Map<String, String> values = getKdcConf();
+ String host = getKdcHost();
+ if (host == null) {
+ host = getWebServer().getBindAddress().getHostName();
+ }
+ values.remove("servers");
+ values.put("_HOST_", host);
+ updateConfFile("kdc.conf", values);
+ } catch (IOException e) {
+ throw new HasException("Failed to update kdc config. ", e);
+ }
+ }
+
+ /**
+ * Start the MySQL connection.
+ *
+ * @param url url of connection
+ * @param user username of connection
+ * @param password password of connection
+ * @throws KrbException e
+ * @return MySQL JDBC connection
+ */
+ private Connection startConnection(String driver, String url, String user,
+ String password) throws HasException {
+ Connection connection;
+ try {
+ Class.forName(driver);
+ connection = DriverManager.getConnection(url, user, password);
+ if (!connection.isClosed()) {
+ LOG.info("Succeeded in connecting to MySQL.");
+ }
+ } catch (ClassNotFoundException e) {
+ throw new HasException("JDBC Driver Class not found. ", e);
+ } catch (SQLException e) {
+ throw new HasException("Failed to connecting to MySQL. ", e);
+ }
+
+ return connection;
+ }
+
+ /**
+ * Config HAS server KDC which have MySQL backend.
+ * @param backendConfig MySQL backend config
+ * @param realm KDC realm to set
+ * @param host KDC host to set
+ * @param hasServer has server to get param
+ * @throws HasException e
+ */
+ public void configMySQLKdc(BackendConfig backendConfig, String realm, int port,
+ String host, HasServer hasServer) throws HasException {
+
+ // Start mysql connection
+ String driver = backendConfig.getString("mysql_driver");
+ String url = backendConfig.getString("mysql_url");
+ String user = backendConfig.getString("mysql_user");
+ String password = backendConfig.getString("mysql_password");
+ Connection connection = startConnection(driver, url, user, password);
+
+ ResultSet resConfig = null;
+ PreparedStatement preStm = null;
+ try {
+ createKdcTable(connection); // Create kdc_config table if not exists
+ String stm = "SELECT * FROM `kdc_config` WHERE id = 1";
+ preStm = connection.prepareStatement(stm);
+ resConfig = preStm.executeQuery();
+ if (!resConfig.next()) {
+ addKdcConfig(connection, realm, port, host);
+ } else {
+ String oldHost = hasServer.getKdcHost();
+ String servers = resConfig.getString("servers");
+ String[] serverArray = servers.split(",");
+ List<String> serverList = new ArrayList<>();
+ Collections.addAll(serverList, serverArray);
+ if (serverList.contains(oldHost)) {
+ servers = servers.replaceAll(oldHost, host);
+ } else {
+ servers = servers + "," + host;
+ }
+ boolean initialized = resConfig.getBoolean("initialized");
+ updateKdcConfig(connection, initialized, port, realm, servers);
+ }
+ hasServer.setKdcHost(host);
+ } catch (SQLException e) {
+ throw new HasException("Failed to config HAS KDC. ", e);
+ } finally {
+ DbUtils.closeQuietly(preStm);
+ DbUtils.closeQuietly(resConfig);
+ DbUtils.closeQuietly(connection);
+ }
+ }
+
+ /**
+ * Create kdc_config table in database.
+ * @param conn database connection
+ * @throws KrbException e
+ */
+ private void createKdcTable(final Connection conn) throws HasException {
+ PreparedStatement preStm = null;
+ try {
+ String stm = "CREATE TABLE IF NOT EXISTS `kdc_config` ("
+ + "port INTEGER DEFAULT 88, servers VARCHAR(255) NOT NULL, "
+ + "initialized bool DEFAULT FALSE, realm VARCHAR(255) "
+ + "DEFAULT NULL, id INTEGER DEFAULT 1, CHECK (id=1), PRIMARY KEY (id)) "
+ + "ENGINE=INNODB;";
+ preStm = conn.prepareStatement(stm);
+ preStm.executeUpdate();
+ } catch (SQLException e) {
+ throw new HasException("Failed to create kdc_config table. ", e);
+ } finally {
+ DbUtils.closeQuietly(preStm);
+ }
+ }
+
+ /**
+ * Add KDC Config information in database.
+ * @param conn database connection
+ * @param realm realm to add
+ * @param port port to add
+ * @param host host to add
+ */
+ private void addKdcConfig(Connection conn, String realm, int port, String host)
+ throws HasException {
+ PreparedStatement preStm = null;
+ try {
+ String stm = "INSERT INTO `kdc_config` (port, servers, realm)" + " VALUES(?, ?, ?)";
+ preStm = conn.prepareStatement(stm);
+ preStm.setInt(1, port);
+ preStm.setString(2, host);
+ preStm.setString(3, realm);
+ preStm.executeUpdate();
+ } catch (SQLException e) {
+ throw new HasException("Failed to insert into kdc_config table. ", e);
+ } finally {
+ DbUtils.closeQuietly(preStm);
+ }
+ }
+
+ /**
+ * Update KDC Config record in database.
+ * @param conn database connection
+ * @param realm realm to update
+ * @param port port to update
+ * @param servers servers to update
+ * @param initialized initial state of KDC Config
+ */
+ private void updateKdcConfig(Connection conn, boolean initialized, int port,
+ String realm, String servers) throws HasException {
+ PreparedStatement preStm = null;
+ try {
+ if (initialized) {
+ String stmUpdate = "UPDATE `kdc_config` SET servers = ? WHERE id = 1";
+ preStm = conn.prepareStatement(stmUpdate);
+ preStm.setString(1, servers);
+ preStm.executeUpdate();
+ } else {
+ String stmUpdate = "UPDATE `kdc_config` SET port = ?, realm = ?, servers = ? WHERE id = 1";
+ preStm = conn.prepareStatement(stmUpdate);
+ preStm.setInt(1, port);
+ preStm.setString(2, realm);
+ preStm.setString(3, servers);
+ preStm.executeUpdate();
+ }
+ } catch (SQLException e) {
+ throw new HasException("Failed to update KDC Config. ", e);
+ } finally {
+ DbUtils.closeQuietly(preStm);
+ }
+ }
+
+ /**
+ * Read in krb5-template.conf and substitute in the correct port.
+ *
+ * @return krb5 conf file
+ * @throws IOException e
+ * @throws KrbException e
+ */
+ public File generateKrb5Conf() throws HasException {
+ Map<String, String> kdcConf = getKdcConf();
+ String[] servers = kdcConf.get("servers").split(",");
+ int kdcPort = Integer.parseInt(kdcConf.get("_PORT_"));
+ String kdcRealm = kdcConf.get("_REALM_");
+ StringBuilder kdcBuilder = new StringBuilder();
+ for (String server : servers) {
+ String append = "\t\tkdc = " + server.trim() + ":" + kdcPort + "\n";
+ kdcBuilder.append(append);
+ }
+ String kdc = kdcBuilder.toString();
+ kdc = kdc.substring(0, kdc.length() - 1);
+ String resourcePath = "/krb5.conf.template";
+ InputStream templateResource = getClass().getResourceAsStream(resourcePath);
+ String content = null;
+ try {
+ content = IOUtil.readInput(templateResource);
+ } catch (IOException e) {
+ throw new HasException("Read template resource failed. " + e);
+ }
+ content = content.replaceAll("_REALM_", kdcRealm);
+ content = content.replaceAll("_PORT_", String.valueOf(kdcPort));
+ content = content.replaceAll("_UDP_LIMIT_", "4096");
+ content = content.replaceAll("_KDCS_", kdc);
+ File confFile = new File(confDir, "krb5.conf");
+ if (confFile.exists()) {
+ boolean delete = confFile.delete();
+ if (!delete) {
+ throw new HasException("File delete error!");
+ }
+ }
+ try {
+ IOUtil.writeFile(content, confFile);
+ } catch (IOException e) {
+ throw new HasException("Write content to conf file failed. " + e);
+ }
+
+ return confFile;
+ }
+
+ /**
+ * Read in has-server.conf and create has-client.conf.
+ *
+ * @return has conf file
+ * @throws IOException e
+ * @throws HasException e
+ */
+ public File generateHasConf() throws HasException, IOException {
+ Map<String, String> kdcConf = getKdcConf();
+ String servers = kdcConf.get("servers");
+ File confFile = new File(getConfDir().getAbsolutePath(), "has-server.conf");
+ HasConfig hasConfig = HasUtil.getHasConfig(confFile);
+ if (hasConfig != null) {
+ String defaultValue = hasConfig.getHttpsHost();
+ InputStream templateResource = new FileInputStream(confFile);
+ String content = IOUtil.readInput(templateResource);
+ content = content.replaceFirst(Pattern.quote(defaultValue), servers);
+ File hasFile = new File(confDir, "has-client.conf");
+ IOUtil.writeFile(content, hasFile);
+ return hasFile;
+ } else {
+ throw new HasException("has-server.conf not found. ");
+ }
+ }
+
public void stopKdcServer() {
try {
kdcServer.stop();
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/ConfFilter.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/ConfFilter.java
index 04c3537..e300886 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/ConfFilter.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/ConfFilter.java
@@ -40,7 +40,7 @@
new File(hasServer.getConfDir(), "has-server.conf"));
String isEnableConf = hasConfig.getEnableConf();
if (!isEnableConf.equals("true")) {
- throw new RuntimeException("The kdc has started.");
+ throw new RuntimeException("The KDC has started, please stop KDC before setting.");
}
filterChain.doFilter(servletRequest, servletResponse);
} catch (HasException e) {
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/ConfigApi.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/ConfigApi.java
new file mode 100644
index 0000000..fdb5cac
--- /dev/null
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/ConfigApi.java
@@ -0,0 +1,278 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.kerby.has.server.web.rest;
+
+import org.apache.kerby.has.common.HasConfig;
+import org.apache.kerby.has.common.HasException;
+import org.apache.kerby.has.common.util.HasUtil;
+import org.apache.kerby.has.server.HasServer;
+import org.apache.kerby.has.server.web.WebServer;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.identity.backend.BackendConfig;
+import org.apache.kerby.kerberos.kerb.server.KdcUtil;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HAS configure web methods implementation.
+ */
+@Path("/conf")
+public class ConfigApi {
+
+ @Context
+ private ServletContext context;
+
+ @Context
+ private HttpServletRequest httpRequest;
+
+ /**
+ * Set HAS plugin.
+ *
+ * @param plugin HAS plugin name
+ * @return Response
+ */
+ @PUT
+ @Path("/setplugin")
+ @Consumes({MediaType.TEXT_PLAIN})
+ @Produces({MediaType.TEXT_PLAIN})
+ public Response setPlugin(@QueryParam("plugin") final String plugin) {
+ if (httpRequest.isSecure()) {
+ final HasServer hasServer = WebServer.getHasServerFromContext(context);
+ WebServer.LOG.info("Set HAS plugin...");
+ String msg;
+ try {
+ Map<String, String> values = new HashMap<>();
+ File hasConfFile = new File(hasServer.getConfDir(), "has-server.conf");
+ HasConfig hasConfig = HasUtil.getHasConfig(hasConfFile);
+ if (hasConfig != null) {
+ String defaultValue = hasConfig.getPluginName();
+ values.put(defaultValue, plugin);
+ } else {
+ msg = "has-server.conf not found.";
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ hasServer.updateConfFile("has-server.conf", values);
+ } catch (IOException | HasException e) {
+ msg = "Failed to set HAS plugin, because: " + e.getMessage();
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ msg = "HAS plugin set successfully.";
+ WebServer.LOG.info(msg);
+ return Response.ok(msg).build();
+ }
+ return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
+ }
+
+ /**
+ * Config HAS server backend.
+ *
+ * @param backendType type of backend
+ * @param dir json dir
+ * @param driver mysql JDBC connector driver
+ * @param url mysql JDBC connector url
+ * @param user mysql user name
+ * @param password mysql password of user
+ * @return Response
+ */
+ @PUT
+ @Path("/configbackend")
+ @Consumes({MediaType.APPLICATION_JSON})
+ @Produces({MediaType.TEXT_PLAIN})
+ public Response configBackend(
+ @QueryParam("backendType") final String backendType,
+ @QueryParam("dir") @DefaultValue("/tmp/has/jsonbackend") final String dir,
+ @QueryParam("driver") @DefaultValue("org.drizzle.jdbc.DrizzleDriver") final String driver,
+ @QueryParam("url") @DefaultValue("jdbc:mysql:thin://127.0.0.1:3306/mysqlbackend") final String url,
+ @QueryParam("user") @DefaultValue("root") final String user,
+ @QueryParam("password") @DefaultValue("passwd") final String password) {
+
+ if (httpRequest.isSecure()) {
+ final HasServer hasServer = WebServer.getHasServerFromContext(context);
+ String msg;
+ if ("json".equals(backendType)) {
+ WebServer.LOG.info("Set Json backend...");
+ try {
+ Map<String, String> values = new HashMap<>();
+ values.put("_JAR_", "org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend");
+ values.put("#_JSON_DIR_", "backend.json.dir = " + dir);
+ values.put("#_MYSQL_\n", "");
+ hasServer.updateConfFile("backend.conf", values);
+ } catch (IOException | HasException e) {
+ msg = "Failed to set Json backend, because: " + e.getMessage();
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ msg = "Json backend set successfully.";
+ WebServer.LOG.info(msg);
+ return Response.ok(msg).build();
+ } else if ("mysql".equals(backendType)) {
+ WebServer.LOG.info("Set MySQL backend...");
+ try {
+ String drizzleUrl = url.replace("jdbc:mysql:", "jdbc:mysql:thin:");
+ String mysqlConfig = "mysql_driver = " + driver + "\nmysql_url = " + drizzleUrl
+ + "\nmysql_user = " + user + "\nmysql_password = " + password;
+ Map<String, String> values = new HashMap<>();
+ values.put("_JAR_", "org.apache.kerby.has.server.kdc.MySQLIdentityBackend");
+ values.put("#_JSON_DIR_\n", "");
+ values.put("#_MYSQL_", mysqlConfig);
+ hasServer.updateConfFile("backend.conf", values);
+ } catch (IOException | HasException e) {
+ msg = "Failed to set MySQL backend, because: " + e.getMessage();
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ msg = "MySQL backend set successfully.";
+ WebServer.LOG.info(msg);
+ return Response.ok(msg).build();
+ } else {
+ msg = backendType + " is not supported.";
+ WebServer.LOG.info(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ }
+ return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
+ }
+
+ /**
+ * Config HAS server KDC.
+ * @param port KDC port to set
+ * @param realm KDC realm to set
+ * @param host KDC host to set
+ * @return Response
+ */
+ @PUT
+ @Path("/configkdc")
+ @Consumes({MediaType.TEXT_PLAIN})
+ @Produces({MediaType.TEXT_PLAIN})
+ public Response configKdc(
+ @QueryParam("port") final int port,
+ @QueryParam("realm") final String realm,
+ @QueryParam("host") final String host) {
+ if (httpRequest.isSecure()) {
+ final HasServer hasServer = WebServer.getHasServerFromContext(context);
+ WebServer.LOG.info("Config HAS server KDC...");
+ String msg;
+ try {
+ BackendConfig backendConfig = KdcUtil.getBackendConfig(hasServer.getConfDir());
+ String backendJar = backendConfig.getString("kdc_identity_backend");
+ if (backendJar.equals("org.apache.kerby.has.server.kdc.MySQLIdentityBackend")) {
+ hasServer.configMySQLKdc(backendConfig, realm, port, host, hasServer);
+ } else {
+ Map<String, String> values = new HashMap<>();
+ values.put("_HOST_", host);
+ values.put("_PORT_", String.valueOf(port));
+ values.put("_REALM_", realm);
+ hasServer.updateConfFile("kdc.conf", values);
+ String kdc = "\t\tkdc = " + host + ":" + port;
+ values.put("_KDCS_", kdc);
+ values.put("_UDP_LIMIT_", "4096");
+ hasServer.updateConfFile("krb5.conf", values);
+ }
+ } catch (IOException | HasException | KrbException e) {
+ msg = "Failed to config HAS KDC, because: " + e.getMessage();
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ msg = "HAS server KDC set successfully.";
+ WebServer.LOG.info(msg);
+ return Response.ok(msg).build();
+ }
+ return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
+ }
+
+ /**
+ * Get krb5.conf file.
+ *
+ * @return Response
+ */
+ @GET
+ @Path("/getkrb5conf")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response getKrb5Conf() {
+ if (httpRequest.isSecure()) {
+ final HasServer hasServer = WebServer.getHasServerFromContext(context);
+ String msg;
+ try {
+ BackendConfig backendConfig = KdcUtil.getBackendConfig(hasServer.getConfDir());
+ String backendJar = backendConfig.getString("kdc_identity_backend");
+ File conf;
+ if (backendJar.equals("org.apache.kerby.has.server.kdc.MySQLIdentityBackend")) {
+ conf = hasServer.generateKrb5Conf();
+ } else {
+ File confDir = hasServer.getConfDir();
+ conf = new File(confDir, "krb5.conf");
+ }
+ return Response.ok(conf).header("Content-Disposition", "attachment; filename=krb5.conf").build();
+ } catch (KrbException | HasException e) {
+ msg = "Failed to get Krb5.conf, because: " + e.getMessage();
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ }
+ return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
+ }
+
+ /**
+ * Get has-client.conf file.
+ *
+ * @return Response
+ */
+ @GET
+ @Path("/gethasclientconf")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response getHasConf() {
+ if (httpRequest.isSecure()) {
+ final HasServer hasServer = WebServer.getHasServerFromContext(context);
+ String msg;
+ try {
+ BackendConfig backendConfig = KdcUtil.getBackendConfig(hasServer.getConfDir());
+ String backendJar = backendConfig.getString("kdc_identity_backend");
+ File conf;
+ if (backendJar.equals("org.apache.kerby.has.server.kdc.MySQLIdentityBackend")) {
+ conf = hasServer.generateHasConf();
+ } else {
+ File confDir = hasServer.getConfDir();
+ conf = new File(confDir, "has-server.conf");
+ }
+ return Response.ok(conf).header("Content-Disposition", "attachment; filename=has-client.conf").build();
+ } catch (IOException | KrbException | HasException e) {
+ msg = "Failed to get has-client.conf, because: " + e.getMessage();
+ WebServer.LOG.error(msg);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
+ }
+ }
+ return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
+ }
+}
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/HadminApi.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/HadminApi.java
index f1ba87c..d91f49d 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/HadminApi.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/HadminApi.java
@@ -257,7 +257,7 @@
return Response.serverError().entity("has-server.conf is not exists.")
.build();
}
- String result = "";
+ String result;
if (isEnable.equals("true")) {
result = "enable";
} else if (isEnable.equals("false")) {
diff --git a/has-project/has-server/src/main/resources/backend.conf.template b/has-project/has-server/src/main/resources/backend.conf.template
new file mode 100644
index 0000000..598be24
--- /dev/null
+++ b/has-project/has-server/src/main/resources/backend.conf.template
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+kdc_identity_backend = _JAR_
+#_JSON_DIR_
+#_MYSQL_
diff --git a/has-project/has-server/src/main/resources/kdc.conf.template b/has-project/has-server/src/main/resources/kdc.conf.template
new file mode 100644
index 0000000..3800cb3
--- /dev/null
+++ b/has-project/has-server/src/main/resources/kdc.conf.template
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+[kdcdefaults]
+ kdc_host = _HOST_
+ kdc_udp_port = _PORT_
+ kdc_tcp_port = _PORT_
+ kdc_realm = _REALM_
diff --git a/has-project/has-server/src/main/resources/krb5.conf.template b/has-project/has-server/src/main/resources/krb5.conf.template
new file mode 100644
index 0000000..ee090c4
--- /dev/null
+++ b/has-project/has-server/src/main/resources/krb5.conf.template
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+[libdefaults]
+ kdc_realm = _REALM_
+ default_realm = _REALM_
+ udp_preference_limit = _UDP_LIMIT_
+ kdc_tcp_port = _PORT_
+ kdc_udp_port = _PORT_
+
+[realms]
+ _REALM_ = {
+_KDCS_
+ }
diff --git a/kerby-dist/has-dist/conf/has-server.conf b/kerby-dist/has-dist/conf/has-server.conf
index 43a83fb..70e643b 100644
--- a/kerby-dist/has-dist/conf/has-server.conf
+++ b/kerby-dist/has-dist/conf/has-server.conf
@@ -22,3 +22,5 @@
filter_auth_type = kerberos
enable_conf = true
+[PLUGIN]
+ auth_type = RAM
diff --git a/pom.xml b/pom.xml
index aea984f..40a4719 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,8 @@
<jersey.container.version>2.17</jersey.container.version>
<jersey.version>1.19</jersey.version>
<commons-text.version>1.1</commons-text.version>
+ <commons-dbutils.version>1.6</commons-dbutils.version>
+ <drizzle-jdbc.version>1.4</drizzle-jdbc.version>
</properties>
<prerequisites>