You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@hive.apache.org by "Muthuraj Ramasamy (JIRA)" <ji...@apache.org> on 2016/09/10 03:30:23 UTC

[jira] [Commented] (HIVE-6517) Improvement on HiveServer2 JDBC: in Kerberos auth mode, accept username / password passed from the client's SessionConf

    [ https://issues.apache.org/jira/browse/HIVE-6517?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15479051#comment-15479051 ] 

Muthuraj Ramasamy commented on HIVE-6517:
-----------------------------------------

Can HiveDriver class be modified to use preauthenticated subject creation in this scenario. Below has the sample code which i used for testing purpose.

Reference : https://issues.apache.org/jira/browse/HIVE-6486
Sample Connection String : jdbc:hive2://%HIVESERVER2%:10000/default;krb5_kdc=%KDC%;principal=hive/%HIVESERVER2%@%REALM%;auth=kerberos;kerberosAuthType=fromSubject

	public Connection connect(final String url, final Properties info) throws SQLException {
		if (url.contains("kerberosAuthType=fromSubject")) {
			return getConnection(url, info);
		} else {
			return acceptsURL(url) ? new HiveConnection(url, info) : null;
		}
	}

	private Connection getConnection(final String url, final Properties info) throws SQLException {
		synchronized (SYNCHRONIZED_OBJ) {
			String[] urlParams = url.split(";");
			String krb5_realm = null;
			String krb5_kdc = null;
			JaasConfiguration jaasConf = new JaasConfiguration();
			Configuration.setConfiguration(jaasConf);
			for (String _urlParam : urlParams) {
				if (_urlParam.contains("principal=")) {
					krb5_realm = _urlParam.replace("krb5_realm=", "");
					krb5_realm = krb5_realm.substring(krb5_realm.indexOf("@") + 1);
				}
				if (_urlParam.contains("krb5_kdc=")) {
					krb5_kdc = _urlParam.replace("krb5_kdc=", "");
				}
			}
			System.setProperty("java.security.krb5.realm", krb5_realm);
			System.setProperty("java.security.krb5.kdc", krb5_kdc);
			String subjectName = "SampleClient" + (new Date().getTime());
			Subject signedOnUserSubject = getSubject(info.getProperty("user"), info.getProperty("password"), krb5_realm, krb5_kdc, subjectName);
			Connection conn = null;
			try {
				conn = (Connection) Subject.doAs(signedOnUserSubject, new PrivilegedExceptionAction<Object>() {
					public Object run() {
						Connection con = null;
						try {
							con = acceptsURL(url) ? new HiveConnection(url, info) : null;
						} catch (SQLException e) {
							e.printStackTrace();
						}
						return con;
					}
				});
			} catch (PrivilegedActionException e) {
				new SQLException(e);
			}
			return conn;
		}
	}

	private static class JaasConfiguration extends Configuration {

		@Override
		public AppConfigurationEntry[] getAppConfigurationEntry(String appName) {
			Map<String, String> krbOptions = new HashMap<String, String>();
			krbOptions.put("refreshKrb5Config", "true");
			krbOptions.put("storeKey", "true");
			AppConfigurationEntry testClientEntry = new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", LoginModuleControlFlag.REQUIRED, krbOptions);
			return new AppConfigurationEntry[] { testClientEntry };
		}
	}

	public class MyCallbackHandler implements CallbackHandler {
		String username = null;
		String krb5_realm = null;
		String krb5_kdc = null;
		String password = null;
		public MyCallbackHandler(String username, String password, String krb5_realm, String krb5_kdc) {
			this.username = username;
			this.krb5_realm = krb5_realm;
			this.krb5_kdc = krb5_kdc;
			this.password = password;
		}

		public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
			for (int i = 0; i < callbacks.length; i++) {
				if (callbacks[i] instanceof NameCallback) {
					NameCallback nc = (NameCallback) callbacks[i];
					nc.setName(username + "@" + krb5_realm);
				} else if (callbacks[i] instanceof PasswordCallback) {
					PasswordCallback nc = (PasswordCallback) callbacks[i];
					nc.setPassword(password.toCharArray());
				} else
					throw new UnsupportedCallbackException(callbacks[i], "Unrecognised callback");
			}
		}
	}

	public Subject getSubject(String username, String password, String krb5_realm, String krb5_kdc, String subjectName) throws SQLException {
		Subject signedOnUserSubject = null;
		LoginContext lc;
		try {
			lc = new LoginContext(subjectName, new MyCallbackHandler(username, password, krb5_realm, krb5_kdc));
			lc.login();
			signedOnUserSubject = lc.getSubject();
		} catch (LoginException e1) {
			throw new SQLException(e1);
		}
		return signedOnUserSubject;
	}

> Improvement on HiveServer2 JDBC: in Kerberos auth mode, accept username / password passed from the client's SessionConf
> -----------------------------------------------------------------------------------------------------------------------
>
>                 Key: HIVE-6517
>                 URL: https://issues.apache.org/jira/browse/HIVE-6517
>             Project: Hive
>          Issue Type: Improvement
>          Components: Authentication, HiveServer2, JDBC
>            Reporter: Jacob Magner
>            Assignee: Prasad Mujumdar
>
> The default JDBC driver ignores username/password completely in Kerberos auth mode.
> To be able to auth from a web interface, we could enable password pass through by changing
> how the Kerberos transport is established. Specifically, we could use LoginContext to authenticate
> with the kdc, and then use the resulting security context to connect with the hive server.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)