org.apache.kerby.kerberos.tool.kadmin.KadminTool Maven / Gradle / Ivy
The newest version!
/**
* 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.
*
*/
package org.apache.kerby.kerberos.tool.kadmin;
import org.apache.kerby.KOptions;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.admin.kadmin.KadminOption;
import org.apache.kerby.kerberos.kerb.admin.kadmin.local.LocalKadmin;
import org.apache.kerby.kerberos.kerb.admin.kadmin.local.LocalKadminImpl;
import org.apache.kerby.kerberos.tool.kadmin.command.AddPrincipalCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.ChangePasswordCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.DeletePrincipalCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.GetPrincipalCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.KadminCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.KeytabAddCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.KeytabRemoveCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.ListPrincipalCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.ModifyPrincipalCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.RenamePrincipalCommand;
import org.apache.kerby.kerberos.tool.kadmin.command.AddPrincipalsCommand;
import org.apache.kerby.util.OSUtil;
import org.jline.reader.Completer;
import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.IOException;
import java.util.Map;
/**
* Ref. MIT kadmin command tool usage.
*/
public class KadminTool {
private static final Logger LOG = LoggerFactory.getLogger(KadminTool.class);
private static File confDir;
private static final String PROMPT = KadminTool.class.getSimpleName() + ".local";
private static final String REQUEST_LIST = "Available " + PROMPT + " requests:\n"
+ "\n"
+ "add_principal, addprinc, ank\n"
+ " Add principal\n"
+ "batch_anks, batch\n"
+ " Add principals\n"
+ "delete_principal, delprinc\n"
+ " Delete principal\n"
+ "modify_principal, modprinc\n"
+ " Modify principal\n"
+ "rename_principal, renprinc\n"
+ " Rename principal\n"
+ "change_password, cpw Change password\n"
+ "get_principal, getprinc Get principal\n"
+ "list_principals, listprincs, get_principals, getprincs\n"
+ " List principals\n"
+ "add_policy, addpol Add policy, not implemented, and will be implemented in next version\n"
+ "modify_policy, modpol Modify policy, not implemented, and will be implemented in next version\n"
+ "delete_policy, delpol Delete policy, not implemented, and will be implemented in next version\n"
+ "get_policy, getpol Get policy, not implemented, and will be implemented in next version\n"
+ "list_policies, listpols, get_policies, getpols, not implemented,"
+ " and will be implemented in next version"
+ " List policies\n"
+ "get_privs, getprivs Get privileges, not implemented, and will be implemented in next version\n"
+ "ktadd, xst Add entry(s) to a keytab\n"
+ "ktremove, ktrem Remove entry(s) from a keytab\n"
+ "lock Lock database exclusively (use with extreme caution!),"
+ " not implemented, and will be implemented in next version\n"
+ "unlock Release exclusive database lock, not implemented,"
+ " and will be implemented in next version\n"
+ "purgekeys Purge previously retained old keys from a principal, "
+ "not implemented, and will be implemented in next version\n"
+ "get_strings, getstrs Show string attributes on a principal, not implemented,"
+ " and will be implemented in next version\n"
+ "set_string, setstr Set a string attribute on a principal, not implemented,"
+ " and will be implemented in next version\n"
+ "del_string, delstr Delete a string attribute on a principal, not implemented,"
+ " and will be implemented in next version\n"
+ "list_requests, lr, ? List available requests.\n"
+ "quit, exit, q Exit program.";
private static final String USAGE = (OSUtil.isWindows()
? "Usage: bin\\kadmin.cmd" : "Usage: sh bin/kadmin.sh")
+ " <-c cache_name>|<-k keytab>\n"
+ "\tExample:\n"
+ "\t\t"
+ (OSUtil.isWindows()
? "bin\\kadmin.cmd" : "sh bin/kadmin.sh")
+ " conf -k admin.keytab\n";
private static void printUsage(String error) {
System.err.println(error + "\n");
System.err.println(USAGE);
System.exit(-1);
}
private static void execute(LocalKadmin kadmin, String command) {
//Omit the leading and trailing whitespace.
command = command.trim();
if (command.equals("list_requests")
|| command.equals("lr")
|| command.equals("?")) {
System.out.println(REQUEST_LIST);
return;
}
KadminCommand executor = null;
if (command.startsWith("add_principal")
|| command.startsWith("addprinc")
|| command.startsWith("ank")) {
executor = new AddPrincipalCommand(kadmin);
} else if (command.startsWith("batch_anks")
|| command.startsWith("batch")) {
executor = new AddPrincipalsCommand(kadmin);
} else if (command.startsWith("ktadd")
|| command.startsWith("xst")) {
executor = new KeytabAddCommand(kadmin);
} else if (command.startsWith("ktremove")
|| command.startsWith("ktrem")) {
executor = new KeytabRemoveCommand(kadmin);
} else if (command.startsWith("delete_principal")
|| command.startsWith("delprinc")) {
executor = new DeletePrincipalCommand(kadmin);
} else if (command.startsWith("modify_principal")
|| command.startsWith("modprinc")) {
executor = new ModifyPrincipalCommand(kadmin);
} else if (command.startsWith("rename_principal")
|| command.startsWith("renprinc")) {
executor = new RenamePrincipalCommand(kadmin);
} else if (command.startsWith("change_password")
|| command.startsWith("cpw")) {
executor = new ChangePasswordCommand(kadmin);
} else if (command.startsWith("list_principals")
|| command.startsWith("listprincs") || command.startsWith("get_principals")
|| command.startsWith("getprincs") || command.startsWith("List principals")) {
executor = new ListPrincipalCommand(kadmin);
} else if (command.startsWith("get_principal") || command.startsWith("getprinc")
|| command.startsWith("Get principal")) {
executor = new GetPrincipalCommand(kadmin);
}
if (executor == null) {
System.out.println("Unknown request \"" + command + "\". Type \"?\" for a request list.");
return;
}
executor.execute(command);
}
private static File getConfDir(String[] args) {
String envDir;
confDir = new File(args[0]);
if (!confDir.exists()) {
try {
Map mapEnv = System.getenv();
envDir = mapEnv.get("KRB5_KDC_DIR");
} catch (SecurityException e) {
envDir = null;
}
if (envDir != null) {
confDir = new File(envDir);
} else {
confDir = new File("/etc/kerby/"); // for Linux. TODO: fix for Win etc.
}
if (!confDir.exists()) {
throw new RuntimeException("Can not locate KDC backend directory "
+ confDir.getAbsolutePath());
}
}
LOG.info("Conf dir:" + confDir.getAbsolutePath());
return confDir;
}
public static void main(String[] args) throws KrbException, IOException {
if (args.length < 2) {
System.err.println(USAGE);
return;
}
LocalKadmin kadmin;
try {
kadmin = new LocalKadminImpl(getConfDir(args));
} catch (KrbException e) {
System.err.println("Failed to init Kadmin due to " + e.getMessage());
return;
}
try {
Krb5Conf krb5Conf = new Krb5Conf(confDir, kadmin.getKdcConfig());
krb5Conf.initKrb5conf();
} catch (IOException e) {
throw new KrbException("Failed to make krb5.conf", e);
}
KOptions kOptions = ToolUtil.parseOptions(args, 1, args.length - 1);
if (kOptions == null) {
System.err.println(USAGE);
return;
}
String kadminPrincipal = kadmin.getKadminPrincipal();
if (kOptions.contains(KadminOption.CCACHE)) {
File ccFile = kOptions.getFileOption(KadminOption.CCACHE);
if (ccFile == null || !ccFile.exists()) {
printUsage("Need the valid credentials cache file.");
return;
}
try {
AuthUtil.loginUsingTicketCache(kadminPrincipal, ccFile);
} catch (LoginException e) {
System.err.println("Could not login with: " + kadminPrincipal
+ " " + e.getMessage());
return;
}
} else if (kOptions.contains(KadminOption.K)) {
File keyTabFile = new File(kOptions.getStringOption(KadminOption.K));
if (!keyTabFile.exists()) {
printUsage("Need the valid keytab file.");
return;
}
try {
AuthUtil.loginUsingKeytab(kadminPrincipal, keyTabFile);
} catch (LoginException e) {
System.err.println("Could not login with: " + kadminPrincipal
+ " " + e.getMessage());
return;
}
} else {
printUsage("No credentials cache file or keytab file for authentication.");
}
// Execute any query that was specified and exit
if (kOptions.contains(KadminOption.QUERY)) {
String query = kOptions.getStringOption(KadminOption.QUERY);
execute(kadmin, query);
} else {
Completer completer = new StringsCompleter("add_principal", "batch_anks", "ktadd", "ktremove",
"delete_principal", "modify_principal", "rename_principal",
"change_password", "list_principals", "get_principal");
Terminal terminal = TerminalBuilder.terminal();
LineReader lineReader = LineReaderBuilder.builder().completer(completer).terminal(terminal).build();
while (true) {
try {
String line = lineReader.readLine(PROMPT + ": ");
if ("quit".equals(line) || "exit".equals(line) || "q".equals(line)) {
break;
}
execute(kadmin, line);
} catch (UserInterruptException | EndOfFileException ex) {
break;
}
}
}
}
}