diff --git a/hadoop-ozone/cli-debug/pom.xml b/hadoop-ozone/cli-debug/pom.xml index 78c2a789b28..01d1f1aa100 100644 --- a/hadoop-ozone/cli-debug/pom.xml +++ b/hadoop-ozone/cli-debug/pom.xml @@ -74,6 +74,10 @@ org.apache.commons commons-lang3 + + org.apache.hadoop + hadoop-auth + org.apache.hadoop hadoop-common diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/authtolocal/KerbNameDebug.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/authtolocal/KerbNameDebug.java new file mode 100644 index 00000000000..cf304e36909 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/authtolocal/KerbNameDebug.java @@ -0,0 +1,67 @@ +/* + * 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.hadoop.ozone.debug.authtolocal; + +import java.util.List; +import java.util.concurrent.Callable; +import org.apache.hadoop.hdds.cli.DebugSubcommand; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.security.authentication.util.KerberosName; +import org.kohsuke.MetaInfServices; +import picocli.CommandLine; + +/** + * Debug command to translate Kerberos principals into local user names + * using the configured auth_to_local rules. + * + * Example: + * ozone debug kerbname testuser/om@EXAMPLE.COM + */ +@CommandLine.Command( + name = "kerbname", + description = "Translate Kerberos principal(s) using auth_to_local rules." +) +@MetaInfServices(DebugSubcommand.class) +public class KerbNameDebug implements Callable, DebugSubcommand { + + @CommandLine.Parameters(arity = "1..*", + description = "Kerberos principal(s) to translate" + ) + private List principals; + + @Override + public Void call() throws Exception { + System.out.println("-- Kerberos Principal Translation --"); + OzoneConfiguration conf = new OzoneConfiguration(); + // Initialize auth_to_local rules + String rules = conf.get("hadoop.security.auth_to_local", "DEFAULT"); + KerberosName.setRules(rules); + System.out.println("auth_to_local rules = " + rules); + for (String principal : principals) { + try { + KerberosName kerbName = new KerberosName(principal); + String shortName = kerbName.getShortName(); + System.out.println(String.format( + "Principal = %s to Local user = %s", principal, shortName)); + } catch (Exception e) { + System.out.println("Failed to translate principal: " + e.getMessage()); + } + } + return null; + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/authtolocal/package-info.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/authtolocal/package-info.java new file mode 100644 index 00000000000..45bfbc16a91 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/authtolocal/package-info.java @@ -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. + */ + +/** + * Auth to local debug related commands. + */ +package org.apache.hadoop.ozone.debug.authtolocal; diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/AuthorizationProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/AuthorizationProbe.java new file mode 100644 index 00000000000..0ed1cf593ea --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/AuthorizationProbe.java @@ -0,0 +1,54 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; + +/** + * Validates Ozone and Hadoop RPC authorization configuration. + */ +public class AuthorizationProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Authorization Configuration"; + } + + @Override + public boolean run() { + System.out.println("-- Authorization Configuration --"); + OzoneConfiguration conf = new OzoneConfiguration(); + + print(conf, "ozone.acl.enabled"); + print(conf, "ozone.acl.authorizer.class"); + print(conf, "hadoop.security.authorization"); + print(conf, "ozone.om.security.client.protocol.acl"); + + print(conf, "hdds.security.client.datanode.container.protocol.acl"); + print(conf, "hdds.security.client.scm.container.protocol.acl"); + print(conf, "hdds.security.client.scm.block.protocol.acl"); + print(conf, "hdds.security.client.scm.certificate.protocol.acl"); + return true; + } + + private void print(OzoneConfiguration conf, String key) { + String value = conf.get(key); + System.out.println(key + " = " + + (value == null ? "(unset)" : value)); + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/DiagnosticProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/DiagnosticProbe.java new file mode 100644 index 00000000000..b08676fee36 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/DiagnosticProbe.java @@ -0,0 +1,28 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +/** + * Interface for a diagnostic probe executed by ozone debug kdiag. + */ +public interface DiagnosticProbe { + + String name(); + + boolean run() throws Exception; +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/EnvironmentProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/EnvironmentProbe.java new file mode 100644 index 00000000000..82935998714 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/EnvironmentProbe.java @@ -0,0 +1,46 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +/** + * Prints environment variables relevant to Kerberos and Ozone. + */ +public class EnvironmentProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Environment Variables"; + } + + @Override + public boolean run() { + System.out.println("-- Environment Variables --"); + print("KRB5_CONFIG"); + print("KRB5CCNAME"); + print("OZONE_CONF_DIR"); + print("HADOOP_CONF_DIR"); + print("JAVA_SECURITY_KRB5_CONF"); + return true; + } + + private void print(String key) { + String value = System.getenv(key); + System.out.println(key + " = " + + (value == null ? "(unset)" : value)); + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/HostProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/HostProbe.java new file mode 100644 index 00000000000..814c47ec439 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/HostProbe.java @@ -0,0 +1,43 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import java.net.InetAddress; + +/** + * Prints host and JVM information. + */ +public class HostProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Host Information"; + } + + @Override + public boolean run() throws Exception { + System.out.println("-- Host Information --"); + System.out.println("Hostname = " + + InetAddress.getLocalHost().getCanonicalHostName()); + System.out.println("User = " + + System.getProperty("user.name")); + System.out.println("Java version = " + + System.getProperty("java.version")); + return true; + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/HttpAuthProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/HttpAuthProbe.java new file mode 100644 index 00000000000..134bd3e02a4 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/HttpAuthProbe.java @@ -0,0 +1,63 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; + +/** + * Prints HTTP Kerberos authentication configuration for Ozone services. + * + * This probe checks whether the HTTP endpoints (WebUI / REST services) + * of Ozone components are configured to use Kerberos authentication. + * + * It only prints configuration values for diagnostics and does not + * enforce validation. Validation can be added in future improvements. + */ +public class HttpAuthProbe implements DiagnosticProbe { + + @Override + public String name() { + return "HTTP Kerberos Authentication"; + } + + @Override + public boolean run() { + + System.out.println("-- HTTP Kerberos Authentication --"); + + OzoneConfiguration conf = new OzoneConfiguration(); + + print(conf, "ozone.om.http.auth.type"); + print(conf, "hdds.scm.http.auth.type"); + print(conf, "hdds.datanode.http.auth.type"); + print(conf, "ozone.s3g.http.auth.type"); + print(conf, "ozone.recon.http.auth.type"); + + return true; + } + + /** + * Helper method to print configuration value. + */ + private void print(OzoneConfiguration conf, String key) { + + String value = conf.get(key); + System.out.println(key + " = " + + (value == null ? "(unset)" : value)); + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/JvmKerberosProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/JvmKerberosProbe.java new file mode 100644 index 00000000000..2be273c1ff8 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/JvmKerberosProbe.java @@ -0,0 +1,49 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +/** + * Prints JVM Kerberos related system properties. + */ +public class JvmKerberosProbe implements DiagnosticProbe { + + @Override + public String name() { + return "JVM Kerberos Properties"; + } + + @Override + public boolean run() { + + System.out.println("-- JVM Kerberos Properties --"); + // Print JVM Kerberos related system properties + print("java.security.krb5.conf"); + print("java.security.krb5.realm"); + print("java.security.krb5.kdc"); + print("sun.security.krb5.debug"); + + return true; + } + + private void print(String key) { + + String value = System.getProperty(key); + System.out.println(key + " = " + + (value == null ? "(unset)" : value)); + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KerberosConfigProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KerberosConfigProbe.java new file mode 100644 index 00000000000..121318999ac --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KerberosConfigProbe.java @@ -0,0 +1,57 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import java.io.File; +import org.apache.hadoop.security.authentication.util.KerberosUtil; + +/** + * Validates Kerberos configuration file and realm. + * + * This probe checks: + * - Location of krb5.conf + * - Default Kerberos realm + * - JVM Kerberos system properties used by Java security + */ +public class KerberosConfigProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Kerberos Configuration"; + } + + @Override + public boolean run() { + System.out.println("-- Kerberos Configuration --"); + // Determine krb5.conf location + String path = System.getenv("KRB5_CONFIG"); + if (path == null) { + path = "/etc/krb5.conf"; + } + File file = new File(path); + System.out.println("krb5.conf = " + file); + try { + String realm = KerberosUtil.getDefaultRealm(); + System.out.println("Default realm = " + realm); + } catch (Exception e) { + System.out.println("WARNING: Unable to determine default realm"); + return false; + } + return file.exists(); + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KerberosTicketProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KerberosTicketProbe.java new file mode 100644 index 00000000000..4627fd112e0 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KerberosTicketProbe.java @@ -0,0 +1,82 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.security.UserGroupInformation; + +/** + * Checks the current Kerberos authentication state of the process. + * + * This probe verifies whether Kerberos security is enabled in configuration, + * what authentication method Hadoop is currently using, and whether a valid + * Kerberos ticket is present in the process ticket cache. + * + * The probe does NOT attempt to perform a login (kinit). Instead it reports + * the current state so operators can diagnose security issues. + */ +public class KerberosTicketProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Kerberos Ticket"; + } + + @Override + public boolean run() { + System.out.println("-- Kerberos Ticket --"); + try { + OzoneConfiguration conf = new OzoneConfiguration(); + // Initialize Hadoop security configuration + UserGroupInformation.setConfiguration(conf); + String authType = conf.get("hadoop.security.authentication"); + boolean securityEnabled = + "kerberos".equalsIgnoreCase(authType); + System.out.println("Security enabled = " + securityEnabled); + UserGroupInformation ugi = + UserGroupInformation.getCurrentUser(); + System.out.println("Login user = " + ugi.getUserName()); + System.out.println("Authentication method = " + + ugi.getAuthenticationMethod()); + boolean hasTicket = ugi.hasKerberosCredentials(); + System.out.println("Kerberos ticket present = " + hasTicket); + String ticketCache = System.getenv("KRB5CCNAME"); + System.out.println("Ticket cache = " + + (ticketCache == null ? "(default cache)" : ticketCache)); + + if (!securityEnabled) { + System.out.println( + "Kerberos security is not enabled in configuration"); + return true; + } + + if (!hasTicket) { + System.out.println( + "WARNING: Kerberos security is enabled but no ticket is loaded"); + System.out.println( + "Run 'kinit' to obtain Kerberos credentials"); + return false; + } + return true; + } catch (Exception e) { + System.out.println( + "ERROR checking kerberos credentials: " + e.getMessage()); + return false; + } + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KeytabProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KeytabProbe.java new file mode 100644 index 00000000000..958a76ee776 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KeytabProbe.java @@ -0,0 +1,65 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import java.io.File; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; + +/** + * Validates existence and readability of Ozone service keytabs. + * + * This probe checks the configured keytab files for major Ozone + * services such as OM, SCM, recon, s3g and DataNode. + */ +public class KeytabProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Keytab Validation"; + } + + @Override + public boolean run() { + System.out.println("-- Keytab Validation --"); + OzoneConfiguration conf = new OzoneConfiguration(); + checkKeytab(conf.get("ozone.om.kerberos.keytab.file")); + checkKeytab(conf.get("hdds.scm.kerberos.keytab.file")); + checkKeytab(conf.get("hdds.datanode.kerberos.keytab.file")); + checkKeytab(conf.get("ozone.recon.kerberos.keytab.file")); + checkKeytab(conf.get("ozone.s3g.kerberos.keytab.file")); + return true; + } + + /** + * Check whether the given keytab exists and is readable. + */ + private void checkKeytab(String path) { + + if (path == null || path.isEmpty()) { + return; + } + File file = new File(path); + if (!file.exists()) { + System.out.println("WARNING: keytab missing: " + path); + } else if (!file.canRead()) { + System.out.println("WARNING: keytab not readable: " + path); + } else { + System.out.println("Keytab OK: " + path); + } + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KinitProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KinitProbe.java new file mode 100644 index 00000000000..251280dfd5c --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/KinitProbe.java @@ -0,0 +1,53 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import java.io.File; + +/** + * Validates that kinit is available on the system PATH. + */ +public class KinitProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Kerberos kinit Command"; + } + + @Override + public boolean run() { + System.out.println("-- Kerberos kinit Command --"); + String path = System.getenv("PATH"); + if (path == null) { + System.out.println("PATH = (unset)"); + System.out.println("kinit cannot be resolved"); + return false; + } + System.out.println("Executable kinit must be available on PATH"); + System.out.println("PATH = " + path); + for (String dir : path.split(":")) { + File candidate = new File(dir, "kinit"); + if (candidate.exists() && candidate.canExecute()) { + System.out.println("kinit found at " + candidate.getAbsolutePath()); + return true; + } + } + System.out.println("kinit not found on PATH"); + return false; + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/OzoneKDiag.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/OzoneKDiag.java new file mode 100644 index 00000000000..df06f227af6 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/OzoneKDiag.java @@ -0,0 +1,77 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import org.apache.hadoop.hdds.cli.DebugSubcommand; +import org.kohsuke.MetaInfServices; +import picocli.CommandLine; + +/** + * Kerberos diagnostic tool for Ozone. + * Usage:Validates each registered probe serially + * and prints diagnostic summary. + * Example: ozone debug kdiag + */ +@CommandLine.Command(name = "kdiag", description = "Diagnose Kerberos configuration issues for Ozone.") +@MetaInfServices(DebugSubcommand.class) +public class OzoneKDiag implements Callable, DebugSubcommand { + @Override + public Void call() throws Exception { + System.out.println("\n== Ozone Kerberos Diagnostics ==\n"); + List probes = + Arrays.asList(new HostProbe(), + new EnvironmentProbe(), + new JvmKerberosProbe(), + new KerberosConfigProbe(), + new KinitProbe(), + new KerberosTicketProbe(), + new PrincipalMappingProbe(), + new OzonePrincipalProbe(), + new KeytabProbe(), + new SecurityConfigProbe(), + new AuthorizationProbe(), + new HttpAuthProbe()); + int pass = 0; + int warn = 0; + int fail = 0; + for (DiagnosticProbe probe : probes) { + try { + boolean result = probe.run(); + if (result) { + pass++; + System.out.println("[PASS] " + probe.name()); + } else { + warn++; + System.out.println("[WARN] " + probe.name()); + } + } catch (Exception e) { + fail++; + System.out.println("[FAIL] " + probe.name() + " : " + e.getMessage()); + } + System.out.println(); + } + System.out.println("== Diagnostic Summary =="); + System.out.println("PASS : " + pass); + System.out.println("WARN : " + warn); + System.out.println("FAIL : " + fail); + return null; + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/OzonePrincipalProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/OzonePrincipalProbe.java new file mode 100644 index 00000000000..e5765589e4b --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/OzonePrincipalProbe.java @@ -0,0 +1,49 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; + +/** + * Prints configured service principals. + */ +public class OzonePrincipalProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Ozone Service Principals"; + } + + @Override + public boolean run() { + System.out.println("-- Ozone Service Principals --"); + OzoneConfiguration conf = new OzoneConfiguration(); + print(conf, "ozone.om.kerberos.principal"); + print(conf, "hdds.scm.kerberos.principal"); + print(conf, "hdds.datanode.kerberos.principal"); + print(conf, "ozone.recon.kerberos.principal"); + print(conf, "ozone.s3g.kerberos.principal"); + return true; + } + + private void print(OzoneConfiguration conf, String key) { + String value = conf.get(key); + System.out.println(key + " = " + + (value == null ? "(unset)" : value)); + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/PrincipalMappingProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/PrincipalMappingProbe.java new file mode 100644 index 00000000000..d17afab950f --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/PrincipalMappingProbe.java @@ -0,0 +1,52 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authentication.util.KerberosName; + +/** + * Validates auth_to_local principal mapping. + */ +public class PrincipalMappingProbe implements DiagnosticProbe { + + @Override + public String name() { + return "auth_to_local mapping"; + } + + @Override + public boolean run() throws Exception { + System.out.println("-- Principal Mapping --"); + OzoneConfiguration conf = new OzoneConfiguration(); + String rules = conf.get("hadoop.security.auth_to_local"); + if (rules == null) { + System.out.println("auth_to_local rules not configured"); + return false; + } + KerberosName.setRules(rules); + String principal = + UserGroupInformation.getLoginUser().getUserName(); + KerberosName name = + new KerberosName(principal); + System.out.println("Principal = " + principal); + System.out.println("Local user = " + name.getShortName()); + return true; + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/SecurityConfigProbe.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/SecurityConfigProbe.java new file mode 100644 index 00000000000..cb897c31668 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/SecurityConfigProbe.java @@ -0,0 +1,70 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; + +/** + * Validates Hadoop and Ozone security configuration. + * + * This probe verifies that Kerberos authentication is enabled + * and prints related security configuration values used by + * Ozone services. + */ +public class SecurityConfigProbe implements DiagnosticProbe { + + @Override + public String name() { + return "Security Configuration"; + } + + @Override + public boolean run() { + System.out.println("-- Security Configuration --"); + OzoneConfiguration conf = new OzoneConfiguration(); + boolean ok = true; + ok &= print(conf, "hadoop.security.authentication"); + print(conf, "ozone.security.enabled"); + print(conf, "ozone.security.http.kerberos.enabled"); + print(conf, "hadoop.rpc.protection"); + print(conf, "hadoop.security.saslproperties.resolver.class"); + print(conf, "ozone.administrators"); + print(conf, "ozone.s3.administrators"); + print(conf, "hdds.block.token.enabled"); + print(conf, "hdds.container.token.enabled"); + print(conf, "hdds.grpc.tls.enabled"); + String auth = conf.get("hadoop.security.authentication"); + if (auth == null) { + System.out.println("WARNING: authentication property not configured"); + return false; + } + if (!"kerberos".equalsIgnoreCase(auth)) { + System.out.println("WARNING: Kerberos security is not enabled"); + return false; + } + System.out.println("Kerberos security is enabled"); + return ok; + } + + private boolean print(OzoneConfiguration conf, String key) { + String value = conf.get(key); + System.out.println(key + " = " + + (value == null ? "(unset)" : value)); + return true; + } +} diff --git a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/package-info.java b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/package-info.java new file mode 100644 index 00000000000..1dacfa4d57d --- /dev/null +++ b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/kdiag/package-info.java @@ -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. + */ + +/** + * Kerberos diagnostic debug related commands. + */ +package org.apache.hadoop.ozone.debug.kdiag; diff --git a/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/authtolocal/TestKerbNameDebug.java b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/authtolocal/TestKerbNameDebug.java new file mode 100644 index 00000000000..fa4b276a633 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/authtolocal/TestKerbNameDebug.java @@ -0,0 +1,72 @@ +/* + * 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.hadoop.ozone.debug.authtolocal; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.hadoop.hdds.utils.IOUtils; +import org.apache.hadoop.ozone.debug.OzoneDebug; +import org.apache.ozone.test.GenericTestUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link KerbNameDebug}. + */ +class TestKerbNameDebug { + + private GenericTestUtils.PrintStreamCapturer out; + + @BeforeEach + void init() { + out = GenericTestUtils.captureOut(); + } + + @Test + void testKerbNameExecution() { + executeKerbName(); + assertOutput(); + } + + private void assertOutput() { + String stdOut = normalize(out.get()); + assertThat(stdOut) + .contains("Kerberos Principal Translation") + .contains("Principal"); + // Translation may succeed or fail depending on auth_to_local rules + assertThat(stdOut) + .containsAnyOf("Local user", "Failed to translate principal"); + } + + @AfterEach + void cleanup() { + IOUtils.closeQuietly(out); + } + + private static void executeKerbName() { + new OzoneDebug().getCmd().execute( + "kerbname", + "testuser/host@EXAMPLE.COM" + ); + } + + private static String normalize(String s) { + return s.replaceAll(" +", " "); + } +} diff --git a/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/authtolocal/package-info.java b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/authtolocal/package-info.java new file mode 100644 index 00000000000..253e7815e1c --- /dev/null +++ b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/authtolocal/package-info.java @@ -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. + */ + +/** + * Tests for auth to local(kerbname). + */ +package org.apache.hadoop.ozone.debug.authtolocal; diff --git a/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/kdiag/TestOzoneKDiag.java b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/kdiag/TestOzoneKDiag.java new file mode 100644 index 00000000000..d5fe73f4483 --- /dev/null +++ b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/kdiag/TestOzoneKDiag.java @@ -0,0 +1,77 @@ +/* + * 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.hadoop.ozone.debug.kdiag; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.hadoop.hdds.utils.IOUtils; +import org.apache.hadoop.ozone.debug.OzoneDebug; +import org.apache.ozone.test.GenericTestUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link OzoneKDiag}. + */ +class TestOzoneKDiag { + + private GenericTestUtils.PrintStreamCapturer out; + + @BeforeEach + void init() { + out = GenericTestUtils.captureOut(); + } + + @Test + void testKDiagExecution() { + executeKDiag(); + assertOutput(); + } + + private void assertOutput() { + + String stdOut = normalize(out.get()); + + assertThat(stdOut) + .contains("Ozone Kerberos Diagnostics") + .contains("Host Information") + .contains("Environment Variables") + .contains("Kerberos Configuration") + .contains("Kerberos Ticket") + .contains("Ozone Service Principals") + .contains("Keytab Validation") + .contains("Security Configuration") + .contains("Authorization Configuration") + .contains("HTTP Kerberos Authentication") + .contains("Diagnostic Summary"); + } + + @AfterEach + void cleanup() { + IOUtils.closeQuietly(out); + } + + private static void executeKDiag() { + new OzoneDebug().getCmd().execute("kdiag"); + } + + private static String normalize(String s) { + return s.replaceAll(" +", " "); + } +} diff --git a/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/kdiag/package-info.java b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/kdiag/package-info.java new file mode 100644 index 00000000000..d279c8c051b --- /dev/null +++ b/hadoop-ozone/cli-debug/src/test/java/org/apache/hadoop/ozone/debug/kdiag/package-info.java @@ -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. + */ + +/** + * Tests for Ozone kerberos diagnostic. + */ +package org.apache.hadoop.ozone.debug.kdiag; diff --git a/hadoop-ozone/dist/src/shell/ozone/ozone b/hadoop-ozone/dist/src/shell/ozone/ozone index 4fe37de1d26..1ad27504d12 100755 --- a/hadoop-ozone/dist/src/shell/ozone/ozone +++ b/hadoop-ozone/dist/src/shell/ozone/ozone @@ -63,6 +63,8 @@ function ozone_usage ozone_add_subcommand "debug" client "Ozone debug tool" ozone_add_subcommand "repair" client "Ozone repair tool" ozone_add_subcommand "ratis" client "Ozone ratis tool" + ozone_add_subcommand "kdiag" client "Kerberos diagnostics tool" + ozone_add_subcommand "kerbname" client "translate Kerberos principal to short name" ozone_generate_usage "${OZONE_SHELL_EXECNAME}" false } @@ -235,6 +237,14 @@ function ozonecmd_case OZONE_CLASSNAME=org.apache.hadoop.ozone.shell.OzoneRatis OZONE_RUN_ARTIFACT_NAME="ozone-tools" ;; + kdiag) + OZONE_CLASSNAME=org.apache.hadoop.security.KDiag + OZONE_RUN_ARTIFACT_NAME="ozone-tools" + ;; + kerbname) + OZONE_CLASSNAME=org.apache.hadoop.ozone.kerberos.KerbName + OZONE_RUN_ARTIFACT_NAME="ozone-tools" + ;; *) OZONE_CLASSNAME="${subcmd}" if ! ozone_validate_classname "${OZONE_CLASSNAME}"; then