/*
* Copyright 2013 Eediom Inc.
*
* Licensed 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.
*/
package org.araqne.logdb.msgbus;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Requires;
import org.araqne.api.PrimitiveConverter;
import org.araqne.api.SystemProperty;
import org.araqne.confdb.Config;
import org.araqne.confdb.ConfigCollection;
import org.araqne.confdb.ConfigDatabase;
import org.araqne.confdb.ConfigService;
import org.araqne.log.api.FieldDefinition;
import org.araqne.logdb.AccountService;
import org.araqne.logdb.AuthServiceNotLoadedException;
import org.araqne.logdb.Permission;
import org.araqne.logdb.Privilege;
import org.araqne.logdb.SecurityGroup;
import org.araqne.logstorage.LockKey;
import org.araqne.logstorage.LockStatus;
import org.araqne.logstorage.LogCryptoProfile;
import org.araqne.logstorage.LogCryptoProfileRegistry;
import org.araqne.logstorage.LogFileService;
import org.araqne.logstorage.LogFileServiceRegistry;
import org.araqne.logstorage.LogRetentionPolicy;
import org.araqne.logstorage.LogStorage;
import org.araqne.logstorage.LogTableRegistry;
import org.araqne.logstorage.StorageConfig;
import org.araqne.logstorage.TableConfig;
import org.araqne.logstorage.TableConfigSpec;
import org.araqne.logstorage.TableSchema;
import org.araqne.msgbus.MessageBus;
import org.araqne.msgbus.MsgbusException;
import org.araqne.msgbus.Request;
import org.araqne.msgbus.Response;
import org.araqne.msgbus.Session;
import org.araqne.msgbus.Token;
import org.araqne.msgbus.TokenApi;
import org.araqne.msgbus.handler.AllowGuestAccess;
import org.araqne.msgbus.handler.CallbackType;
import org.araqne.msgbus.handler.MsgbusMethod;
import org.araqne.msgbus.handler.MsgbusPlugin;
@Component(name = "logdb-management-msgbus")
@MsgbusPlugin
public class ManagementPlugin {
private final org.slf4j.Logger slog = org.slf4j.LoggerFactory.getLogger(ManagementPlugin.class.getName());
@Requires
private AccountService accountService;
@Requires
private LogTableRegistry tableRegistry;
@Requires
private MessageBus msgbus;
@Requires
private LogStorage storage;
@Requires
private LogFileServiceRegistry lfsRegistry;
@Requires
private LogCryptoProfileRegistry logCryptoProfileRegistry;
// TODO: move system variables control to storage service
@Requires
private ConfigService conf;
@Requires
private TokenApi tokenApi;
@AllowGuestAccess
@MsgbusMethod
public void login(Request req, Response resp) {
Session session = req.getSession();
if (session.get("araqne_logdb_session") != null)
throw new MsgbusException("logdb", "already-logon");
org.araqne.logdb.Session dbSession = null;
String loginName = null;
// authenticate using msgbus token api
String t = req.getString("token");
if (t != null) {
Token token = tokenApi.getToken(t);
if (token == null || (token.getData() == null || !token.getData().toString().equals("logdb-auth-token")))
throw new MsgbusException("logdb", "invalid-token");
tokenApi.removeToken(t);
loginName = token.getSession().getAdminLoginName();
dbSession = accountService.newSession(loginName);
dbSession.setProperty("remote_ip", getRemoteAddr(session));
} else {
loginName = req.getString("login_name", true);
String password = req.getString("password", true);
if (slog.isDebugEnabled())
slog.debug("araqne logdb: trying to login [{}] from [{}]", loginName, session.getRemoteAddress().getHostAddress());
try {
dbSession = accountService.login(loginName, password);
dbSession.setProperty("remote_ip", getRemoteAddr(session));
if (slog.isDebugEnabled())
slog.debug("araqne logdb: [{}] is logged in successfully from [{}]", loginName, session.getRemoteAddress()
.getHostAddress());
} catch (AuthServiceNotLoadedException e) {
Boolean useErrorReturn = req.getBoolean("use_error_return");
if (useErrorReturn != null && useErrorReturn) {
slog.info("logdb external auth service is not loaded: " + e.getAuthService());
resp.put("error_code", "99000"); // XXX
return;
} else {
throw e;
}
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().equals("invalid password")) {
Map<String, Object> errorParams = new HashMap<String, Object>();
errorParams.put("login", loginName);
errorParams.put("remote_ip", getRemoteAddr(session));
throw new MsgbusException("logdb", "invalid password", errorParams);
}
throw e;
}
}
dbSession.setProperty("locale", session.getLocale());
if (session.getOrgDomain() == null && session.getAdminLoginName() == null) {
session.setProperty("org_domain", "localhost");
session.setProperty("admin_login_name", loginName);
session.setProperty("auth", "logdb");
}
session.setProperty("araqne_logdb_session", dbSession);
}
private String getRemoteAddr(Session session) {
return session.getRemoteAddress() != null ? session.getRemoteAddress().getHostAddress() : null;
}
@MsgbusMethod
public void logout(Request req, Response resp) {
Session session = req.getSession();
org.araqne.logdb.Session dbSession = (org.araqne.logdb.Session) session.get("araqne_logdb_session");
if (dbSession != null) {
try {
accountService.logout(dbSession);
} catch (Throwable t) {
}
session.unsetProperty("araqne_logdb_session");
}
String auth = session.getString("auth");
if (auth != null && auth.equals("logdb"))
msgbus.closeSession(session);
}
@MsgbusMethod(type = CallbackType.SessionClosed)
public void onClose(Session session) {
if (session == null)
return;
try {
org.araqne.logdb.Session dbSession = (org.araqne.logdb.Session) session.get("araqne_logdb_session");
if (dbSession != null) {
try {
accountService.logout(dbSession);
} catch (Throwable t) {
}
session.unsetProperty("araqne_logdb_session");
}
} catch (ClassCastException e) {
// ignore (error after bundle update)
}
}
@MsgbusMethod
public void listAccounts(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
List<Object> accounts = new ArrayList<Object>();
for (String loginName : accountService.getAccountNames()) {
List<Privilege> privileges = accountService.getPrivileges(session, loginName);
Map<String, Object> m = new HashMap<String, Object>();
m.put("login_name", loginName);
m.put("privileges", serialize(privileges));
accounts.add(m);
}
resp.put("accounts", accounts);
}
@MsgbusMethod
public void getInstanceGuid(Request req, Response resp) {
resp.put("instance_guid", accountService.getInstanceGuid());
}
private List<Object> serialize(List<Privilege> privileges) {
List<Object> l = new ArrayList<Object>();
for (Privilege p : privileges)
l.add(PrimitiveConverter.serialize(p));
return l;
}
@MsgbusMethod
public void changePassword(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
String password = req.getString("password", true);
accountService.changePassword(session, loginName, password);
}
@MsgbusMethod
public void createAccount(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
String password = req.getString("password", true);
accountService.createAccount(session, loginName, password);
}
@MsgbusMethod
public void removeAccount(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
accountService.removeAccount(session, loginName);
}
@MsgbusMethod
public void getPrivileges(Request req, Response resp) {
org.araqne.logdb.Session session = ensureDbSession(req);
String loginName = req.getString("login_name", true);
List<Privilege> privileges = accountService.getPrivileges(session, loginName);
Map<String, List<String>> m = new HashMap<String, List<String>>();
List<String> l = Arrays.asList(Permission.READ.toString());
for (Privilege p : privileges)
m.put(p.getTableName(), l);
resp.putAll(m);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void setPrivileges(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
List<String> tableNames = (List<String>) req.get("table_names", true);
List<Privilege> privileges = new ArrayList<Privilege>();
for (String tableName : tableNames)
privileges.add(new Privilege(loginName, tableName, Permission.READ));
accountService.setPrivileges(session, loginName, privileges);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void setTablePrivileges(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String tableName = req.getString("table_name", true);
if (tableRegistry.getTableSchema(tableName) == null)
throw new MsgbusException("logdb", "table not found:" + tableName);
// set newer table privileges
List<String> loginNames = (List<String>) req.get("login_names", true);
List<Privilege> privileges = new ArrayList<Privilege>();
for (String loginName : loginNames)
privileges.add(new Privilege(loginName, tableName, Permission.READ));
// add other old table privileges
for (Privilege privilige : accountService.getPrivileges(session, null)) {
if (privilige.getTableName().equals(tableName))
continue;
privileges.add(privilige);
}
accountService.resetPrivileges(session, privileges);
List<String> groups = (List<String>) req.get("security_groups", true);
List<SecurityGroup> updateGroups = new ArrayList<SecurityGroup>();
for (SecurityGroup group : accountService.getSecurityGroups()) {
if (groups.contains(group.getName())) {
if (!group.getReadableTables().contains(tableName)) {
group.getReadableTables().add(tableName);
updateGroups.add(group);
}
} else {
if (group.getReadableTables().contains(tableName)) {
group.getReadableTables().remove(tableName);
updateGroups.add(group);
}
}
}
if (!updateGroups.isEmpty())
accountService.updateSecurityGroups(session, updateGroups);
}
/**
* @since 2.4.28
*/
@MsgbusMethod
public void grantAdmin(Request req, Response resp) {
String loginName = req.getString("login_name", true);
org.araqne.logdb.Session session = ensureAdminSession(req);
accountService.grantAdmin(session, loginName);
}
/**
* @since 2.4.28
*/
@MsgbusMethod
public void revokeAdmin(Request req, Response resp) {
String loginName = req.getString("login_name", true);
org.araqne.logdb.Session session = ensureAdminSession(req);
accountService.revokeAdmin(session, loginName);
}
@MsgbusMethod
public void grantPrivilege(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
String tableName = req.getString("table_name", true);
accountService.grantPrivilege(session, loginName, tableName, Permission.READ);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void grantPrivileges(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
List<String> tableNames = (List<String>) req.get("table_names", true);
for (String tableName : tableNames)
accountService.grantPrivilege(session, loginName, tableName, Permission.READ);
}
@MsgbusMethod
public void revokePrivilege(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
String tableName = req.getString("table_name", true);
accountService.revokePrivilege(session, loginName, tableName, Permission.READ);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void revokePrivileges(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
String loginName = req.getString("login_name", true);
List<String> tableNames = (List<String>) req.get("table_names");
for (String tableName : tableNames)
accountService.revokePrivilege(session, loginName, tableName, Permission.READ);
}
/**
* @since 2.6.34
*/
@MsgbusMethod
public void listSecurityGroups(Request req, Response resp) {
List<SecurityGroup> groups = accountService.getSecurityGroups();
Boolean isUserFilter = req.has("user_filter") ? req.getBoolean("user_filter") : false;
String reqLoginName = req.getSession().getAdminLoginName();
// return without details
List<Object> l = new ArrayList<Object>();
for (SecurityGroup group : groups) {
if (isUserFilter && !group.getAccounts().contains(reqLoginName))
continue;
Map<String, Object> m = new HashMap<String, Object>();
m.put("guid", group.getGuid());
m.put("name", group.getName());
m.put("description", group.getDescription());
m.put("created", group.getCreated());
m.put("updated", group.getUpdated());
l.add(m);
}
resp.put("security_groups", l);
}
/**
* @since 2.6.34
*/
@MsgbusMethod
public void getSecurityGroup(Request req, Response resp) {
String guid = req.getString("guid", true);
SecurityGroup group = accountService.getSecurityGroup(guid);
resp.put("security_group", group == null ? null : group.marshal());
}
@MsgbusMethod
public void isMemberOfSecurityGroup(Request req, Response resp) {
String guid = req.getString("guid", true);
SecurityGroup group = accountService.getSecurityGroup(guid);
if (group == null)
throw new MsgbusException("logdb", "security group not found:" + guid);
resp.put("result", group.getAccounts().contains(req.getSession().getAdminLoginName()));
}
/**
* @since 2.6.34
*/
@SuppressWarnings("unchecked")
@MsgbusMethod
public void createSecurityGroup(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
SecurityGroup group = new SecurityGroup();
if (req.get("guid") != null)
group.setGuid(req.getString("guid"));
group.setName(req.getString("name", true));
group.setDescription(req.getString("description"));
if (req.get("table_names") != null)
group.setReadableTables(new HashSet<String>((List<String>) req.get("table_names")));
if (req.get("accounts") != null)
group.setAccounts(new HashSet<String>((List<String>) req.get("accounts")));
try {
accountService.createSecurityGroup(session, group);
} catch (IllegalStateException e) {
throw new MsgbusException("logdb", e.getMessage());
}
resp.put("guid", group.getGuid());
}
/**
* @since 2.6.34
*/
@SuppressWarnings("unchecked")
@MsgbusMethod
public void updateSecurityGroup(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
SecurityGroup group = accountService.getSecurityGroup(req.getString("guid", true));
if (group == null)
throw new MsgbusException("logdb", "security group not found");
group.setName(req.getString("name", true));
group.setDescription(req.getString("description"));
group.setAccounts(new HashSet<String>((List<String>) req.get("accounts", true)));
group.setReadableTables(new HashSet<String>((List<String>) req.get("table_names", true)));
accountService.updateSecurityGroup(session, group);
}
/**
* @since 2.6.34
*/
@SuppressWarnings("unchecked")
@MsgbusMethod
public void removeSecurityGroups(Request req, Response resp) {
org.araqne.logdb.Session session = ensureAdminSession(req);
List<String> guids = (List<String>) req.get("group_guids", true);
List<String> failed = new ArrayList<String>();
for (String guid : guids) {
try {
accountService.removeSecurityGroup(session, guid);
} catch (Throwable t) {
failed.add(guid);
slog.error("araqne logdb: cannot remove security group [" + guid + "]", t);
}
}
resp.put("failed_groups", failed);
}
@MsgbusMethod
public void listTables(Request req, Response resp) {
org.araqne.logdb.Session session = ensureDbSession(req);
Map<String, Object> schemas = new HashMap<String, Object>();
Map<String, Object> tables = new HashMap<String, Object>();
Map<String, Object> fields = new HashMap<String, Object>();
Map<String, Object> locks = new HashMap<String, Object>();
Map<String, Object> owners = new HashMap<String, Object>();
Map<String, Object> purposes = new HashMap<String, Object>();
if (session.isAdmin()) {
for (TableSchema schema : tableRegistry.getTableSchemas()) {
schemas.put(schema.getName(), schema.marshal());
tables.put(schema.getName(), getTableMetadata(schema));
LockStatus s = storage.lockStatus(new LockKey("script", schema.getName(), null));
locks.put(schema.getName(), s.isLocked());
owners.put(schema.getName(), s.getOwner());
purposes.put(schema.getName(), s.getPurposes());
List<FieldDefinition> defs = schema.getFieldDefinitions();
if (defs != null)
fields.put(schema.getName(), PrimitiveConverter.serialize(defs));
}
} else {
List<Privilege> privileges = accountService.getPrivileges(session, session.getLoginName());
for (Privilege p : privileges) {
if (p.getPermissions().size() > 0 && tableRegistry.exists(p.getTableName())) {
TableSchema schema = tableRegistry.getTableSchema(p.getTableName(), true);
schemas.put(p.getTableName(), schema.marshal());
tables.put(schema.getName(), getTableMetadata(schema));
LockStatus s = storage.lockStatus(new LockKey("script", schema.getName(), null));
locks.put(schema.getName(), s.isLocked());
owners.put(schema.getName(), s.getOwner());
purposes.put(schema.getName(), s.getPurposes());
List<FieldDefinition> defs = schema.getFieldDefinitions();
if (defs != null)
fields.put(schema.getName(), PrimitiveConverter.serialize(defs));
}
}
}
resp.put("schemas", schemas);
// for backward compatibility
resp.put("tables", tables);
resp.put("fields", fields);
resp.put("locks", locks);
resp.put("owners", owners);
resp.put("purposes", purposes);
}
@MsgbusMethod
public void getTableInfo(Request req, Response resp) {
String tableName = req.getString("table", true);
checkTableAccess(req, tableName, Permission.READ);
TableSchema schema = tableRegistry.getTableSchema(tableName);
if (schema == null)
throw new MsgbusException("logdb", "table-not-found");
resp.put("schema", schema.marshal());
// for backward compatibility
List<FieldDefinition> defs = schema.getFieldDefinitions();
if (defs != null)
resp.put("fields", PrimitiveConverter.serialize(defs));
resp.put("table", getTableMetadata(schema));
}
private Map<String, Object> getTableMetadata(TableSchema schema) {
Map<String, Object> metadata = new HashMap<String, Object>();
Map<String, String> strings = schema.getMetadata();
for (String key : strings.keySet()) {
metadata.put(key, strings.get(key));
}
return metadata;
}
/**
* @since 2.0.3
*/
@SuppressWarnings("unchecked")
@MsgbusMethod
public void setTableFields(Request req, Response resp) {
ensureAdminSession(req);
String tableName = req.getString("table", true);
List<Object> l = (List<Object>) req.get("fields");
List<FieldDefinition> fields = null;
if (l != null) {
fields = new ArrayList<FieldDefinition>();
for (Object o : l) {
Map<String, Object> m = (Map<String, Object>) o;
FieldDefinition f = new FieldDefinition();
f.setName((String) m.get("name"));
f.setType((String) m.get("type"));
f.setLength((Integer) m.get("length"));
fields.add(f);
}
}
TableSchema schema = tableRegistry.getTableSchema(tableName, true);
schema.setFieldDefinitions(fields);
tableRegistry.alterTable(tableName, schema);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void setTableMetadata(Request req, Response resp) {
ensureAdminSession(req);
String tableName = req.getString("table", true);
Map<String, Object> metadata = (Map<String, Object>) req.get("metadata", true);
TableSchema schema = tableRegistry.getTableSchema(tableName, true);
for (String key : metadata.keySet()) {
Object value = metadata.get(key);
schema.getMetadata().put(key, value == null ? null : value.toString());
}
tableRegistry.alterTable(tableName, schema);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void unsetTableMetadata(Request req, Response resp) {
ensureAdminSession(req);
String tableName = req.getString("table", true);
List<Object> keys = (List<Object>) req.get("keys", true);
TableSchema schema = tableRegistry.getTableSchema(tableName, true);
Map<String, String> metadata = schema.getMetadata();
for (Object key : keys) {
metadata.remove(key.toString());
}
tableRegistry.alterTable(tableName, schema);
}
private void checkTableAccess(Request req, String tableName, Permission permission) {
org.araqne.logdb.Session session = (org.araqne.logdb.Session) req.getSession().get("araqne_logdb_session");
if (session == null)
throw new MsgbusException("logdb", "no-logdb-session");
boolean allowed = session.isAdmin() || accountService.checkPermission(session, tableName, permission);
if (!allowed)
throw new MsgbusException("logdb", "no-permission");
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void createTable(Request req, Response resp) {
ensureAdminSession(req);
String tableName = req.getString("table", true);
String engineType = req.getString("type", true);
String basePath = req.getString("base_path");
if (basePath != null) {
// normalize local path (prevent C://)
basePath = new File(basePath).getAbsolutePath();
}
Map<String, String> primaryConfigs = (Map<String, String>) req.get("primary_configs");
if (primaryConfigs == null)
primaryConfigs = new HashMap<String, String>();
Map<String, String> replicaConfigs = (Map<String, String>) req.get("replica_configs");
Map<String, String> metadata = (Map<String, String>) req.get("metadata");
LogFileService lfs = lfsRegistry.getLogFileService(engineType);
StorageConfig primaryStorage = new StorageConfig(engineType, basePath);
for (TableConfigSpec spec : lfs.getConfigSpecs()) {
String value = primaryConfigs.get(spec.getKey());
if (value != null) {
if (spec.getValidator() != null)
spec.getValidator().validate(spec.getKey(), Arrays.asList(value));
primaryStorage.getConfigs().add(new TableConfig(spec.getKey(), value));
} else if (!spec.isOptional())
throw new MsgbusException("logdb", "table-config-missing");
}
StorageConfig replicaStorage = null;
if (replicaConfigs != null) {
replicaStorage = primaryStorage.clone();
for (TableConfigSpec spec : lfs.getReplicaConfigSpecs()) {
String value = replicaConfigs.get(spec.getKey());
if (value != null) {
if (spec.getValidator() != null)
spec.getValidator().validate(spec.getKey(), Arrays.asList(value));
replicaStorage.getConfigs().add(new TableConfig(spec.getKey(), value));
} else if (!spec.isOptional())
throw new MsgbusException("logdb", "table-config-missing");
}
}
TableSchema schema = new TableSchema();
schema.setName(tableName);
schema.setPrimaryStorage(primaryStorage);
schema.setReplicaStorage(replicaStorage);
schema.setMetadata(metadata);
storage.createTable(schema);
}
@MsgbusMethod
public void dropTable(Request req, Response resp) {
ensureAdminSession(req);
String tableName = req.getString("table", true);
try {
storage.dropTable(tableName);
} catch(Throwable t) {
throw new MsgbusException("logdb", "cannot-drop-locked-table", p("table_name", tableName));
}
}
@MsgbusMethod
public void dropTables(Request req, Response resp) {
ensureAdminSession(req);
@SuppressWarnings("unchecked")
List<String> tableNames = (List<String>) req.get("tables", true);
List<String> dropFailedTableNames = new ArrayList<String>();
for (String name : tableNames) {
try {
storage.dropTable(name);
} catch(Throwable t) {
dropFailedTableNames.add(name);
}
}
if(dropFailedTableNames.size() > 0)
throw new MsgbusException("logdb", "cannot-drop-locked-table", p("table_names", dropFailedTableNames));
}
private org.araqne.logdb.Session ensureAdminSession(Request req) {
org.araqne.logdb.Session session = (org.araqne.logdb.Session) req.getSession().get("araqne_logdb_session");
if (session != null && !session.isAdmin())
throw new SecurityException("logdb management is not allowed to " + session.getLoginName());
return session;
}
private org.araqne.logdb.Session ensureDbSession(Request req) {
org.araqne.logdb.Session session = (org.araqne.logdb.Session) req.getSession().get("araqne_logdb_session");
if (session == null)
throw new SecurityException("logdb session not found: " + req.getSession().getAdminLoginName());
return session;
}
@MsgbusMethod
public void purge(Request req, Response resp) {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
String tableName = req.getString("table");
Date fromDay = null;
Date toDay = null;
try {
fromDay = df.parse(req.getString("from_day"));
toDay = df.parse(req.getString("to_day"));
} catch (ParseException e) {
throw new MsgbusException("logdb", "not-parse-date");
}
if ((fromDay != null && toDay != null) && fromDay.after(toDay))
throw new IllegalArgumentException("araqne-logdb: invalid date range(from: " + fromDay + ", to: " + toDay);
storage.purge(tableName, fromDay, toDay);
}
@MsgbusMethod
public void getLogDates(Request req, Response resp) {
String tableName = req.getString("table");
Collection<Date> logDates = storage.getLogDates(tableName);
resp.put("logdates", logDates);
}
@MsgbusMethod
public void getCryptoProfiles(Request req, Response resp) {
List<Object> l = new ArrayList<Object>();
for (LogCryptoProfile p : logCryptoProfileRegistry.getProfiles()) {
Map<String, Object> m = serialize(p);
l.add(m);
}
resp.put("profiles", l);
}
private Map<String, Object> serialize(LogCryptoProfile profile) {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", profile.getName());
m.put("cipher", profile.getCipher());
m.put("digest", profile.getDigest());
m.put("file_path", profile.getFilePath());
return m;
}
@MsgbusMethod
public void getCryptoProfile(Request req, Response resp) {
String name = req.getString("name");
resp.put("profile", logCryptoProfileRegistry.getProfile(name));
}
@MsgbusMethod
public void addCryptoProfile(Request req, Response resp) {
String name = req.getString("name", true);
String cipher = req.getString("cipher");
String digest = req.getString("digest");
String filePath = req.getString("file_path", true);
String password = req.getString("password");
FileInputStream is = null;
try {
File f = new File(filePath);
if (!f.exists())
throw new MsgbusException("logdb", "file-not-found");
is = new FileInputStream(f);
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(is, password == null ? null : password.toCharArray());
} catch (MsgbusException e) {
throw e;
} catch (Throwable t) {
slog.error("araqne logdb: cannot add crypto profile [" + name + "]", t);
throw new MsgbusException("logdb", "check-password");
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
LogCryptoProfile p = new LogCryptoProfile();
p.setName(name);
p.setCipher(cipher);
p.setDigest(digest);
p.setFilePath(filePath);
p.setPassword(password);
try {
logCryptoProfileRegistry.addProfile(p);
} catch (IllegalStateException e) {
throw new MsgbusException("logpresso", "duplicated-crypto-profile");
}
}
@MsgbusMethod
public void removeCryptoProfile(Request req, Response resp) {
String name = req.getString("name");
logCryptoProfileRegistry.removeProfile(name);
}
@MsgbusMethod
public void getCipherTransformers(Request req, Response resp) {
List<String> l = new ArrayList<String>();
l.add("AES/CBC/NoPadding");
l.add("AES/CBC/PKCS5Padding");
l.add("AES/ECB/NoPadding");
l.add("AES/ECB/PKCS5Padding");
l.add("DES/CBC/NoPadding");
l.add("DES/CBC/PKCS5Padding");
l.add("DES/ECB/NoPadding");
l.add("DES/ECB/PKCS5Padding");
l.add("DESede/CBC/NoPadding");
l.add("DESede/CBC/PKCS5Padding");
l.add("DESede/ECB/NoPadding");
l.add("DESede/ECB/PKCS5Padding");
l.add("RSA/ECB/PKCS1Padding");
l.add("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
l.add("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
resp.put("cipher_transformers", l);
}
@MsgbusMethod
public void getStorageEngines(Request req, Response resp) {
Locale locale = req.getSession().getLocale();
String s = req.getString("locale");
if (s != null)
locale = new Locale(s);
List<Object> engines = new ArrayList<Object>();
for (String name : lfsRegistry.getInstalledTypes()) {
// prevent hang
if (name.equals("v1"))
continue;
LogFileService lfs = lfsRegistry.getLogFileService(name);
Map<String, Object> engine = new HashMap<String, Object>();
engine.put("type", name);
List<Object> primarySpecs = new ArrayList<Object>();
for (TableConfigSpec spec : lfs.getConfigSpecs())
primarySpecs.add(marshal(spec, locale));
List<Object> replicaSpecs = new ArrayList<Object>();
for (TableConfigSpec spec : lfs.getReplicaConfigSpecs())
replicaSpecs.add(marshal(spec, locale));
engine.put("primary_config_specs", primarySpecs);
engine.put("replica_config_specs", replicaSpecs);
engines.add(engine);
}
resp.put("engines", engines);
}
private Map<String, Object> marshal(TableConfigSpec spec, Locale locale) {
String displayName = spec.getDisplayNames().get(locale);
if (displayName == null)
displayName = spec.getDisplayNames().get(Locale.ENGLISH);
String description = spec.getDescriptions().get(locale);
if (description == null)
description = spec.getDescriptions().get(Locale.ENGLISH);
Map<String, Object> m = new HashMap<String, Object>();
m.put("type", spec.getType().toString().toLowerCase());
m.put("key", spec.getKey());
m.put("optional", spec.isOptional());
m.put("updatable", spec.isUpdatable());
m.put("display_name", displayName);
m.put("description", description);
m.put("enums", spec.getEnums());
return m;
}
@MsgbusMethod
public void setRetention(Request req, Response resp) {
ensureAdminSession(req);
String tableName = req.getString("table", true);
int retention = req.getInteger("retention", true);
if (!tableRegistry.exists(tableName))
throw new MsgbusException("logdb", "table-not-found");
if (retention < 0)
throw new MsgbusException("logdb", "invalid-retention");
LogRetentionPolicy p = new LogRetentionPolicy();
p.setTableName(tableName);
p.setRetentionDays(retention);
storage.setRetentionPolicy(p);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void getSystemVariables(Request req, Response resp) {
ConfigDatabase db = conf.ensureDatabase("araqne-logstorage");
ConfigCollection col = db.ensureCollection("global_settings");
Config c = col.findOne(null);
Map<String, Object> m = new HashMap<String, Object>();
if (c != null && c.getDocument() != null)
m = (Map<String, Object>) c.getDocument();
Map<String, Object> vars = new HashMap<String, Object>();
for (String key : Arrays.asList("min_free_disk_space_type", "min_free_disk_space_value", "disk_lack_action")) {
Object var = m.get(key);
if (key.equals("min_free_disk_space_type") && var == null)
var = "Percentage";
if (key.equals("min_free_disk_space_value") && var == null)
var = "5";
if (key.equals("disk_lack_action") && var == null)
var = "RemoveOldLog";
vars.put(key, var);
}
resp.put("vars", vars);
}
@SuppressWarnings("unchecked")
@MsgbusMethod
public void setSystemVariables(Request req, Response resp) {
ConfigDatabase db = conf.ensureDatabase("araqne-logstorage");
ConfigCollection col = db.ensureCollection("global_settings");
Config c = col.findOne(null);
Map<String, Object> m = new HashMap<String, Object>();
if (c != null)
m = (Map<String, Object>) c.getDocument();
String minFreeDiskSpaceType = (String) req.get("min_free_disk_space_type");
if (minFreeDiskSpaceType != null) {
if (!minFreeDiskSpaceType.equals("Percentage") && !minFreeDiskSpaceType.equals("Megabyte"))
throw new MsgbusException("logdb", "invalid-unit");
else
m.put("min_free_disk_space_type", minFreeDiskSpaceType);
}
String minFreeDiskSpaceValue = (String) req.get("min_free_disk_space_value");
if (minFreeDiskSpaceValue != null) {
try {
Long.valueOf(minFreeDiskSpaceValue);
m.put("min_free_disk_space_value", minFreeDiskSpaceValue);
} catch (NumberFormatException e) {
throw new MsgbusException("logdb", "invalid-number-format");
}
}
String diskLackAction = (String) req.get("disk_lack_action");
if (diskLackAction != null) {
if ((!diskLackAction.equals("StopLogging") && !diskLackAction.equals("RemoveOldLog")))
throw new MsgbusException("logdb", "invalid-disk-lack-action");
else {
if(SystemProperty.isEnabled("cc_compliant"))
m.put("disk_lack_action", "RemoveOldLog");
else
m.put("disk_lack_action", diskLackAction);
}
}
if (c != null) {
c.setDocument(m);
c.update();
} else {
col.add(m);
}
}
private Map<String, Object> p(String k, Object v) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(k, v);
return params;
}
}