You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by Jonathan Gallimore <jo...@gmail.com> on 2019/12/06 10:39:24 UTC

HTTP connector via Proxy with Kerberos

Hi

I have a standalone client application that sends messages to a queue using
the HTTP connector. That connector has the ability to pass a
username/password for proxy authentication with the basic scheme.

I have a requirement to use Kerberos, and have adjusted the code
in HttpClientTransport.createHttpClient() with a relatively straightforward
change to enable this (as HttpClient has support for this), and the code I
have looks like this:

    protected HttpClient createHttpClient() {
        HttpClientBuilder clientBuilder = HttpClientBuilder.create();
        clientBuilder.setConnectionManager(createClientConnectionManager());
        if (useCompression) {
            clientBuilder.addInterceptorLast(new HttpRequestInterceptor() {
                @Override
                public void process(HttpRequest request, HttpContext
context) {
                    // We expect to received a compression response that we
un-gzip
                    request.addHeader("Accept-Encoding", "gzip");
                }
            });
        }

        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
        if (getProxyHost() != null) {
            HttpHost proxy = new HttpHost(getProxyHost(), getProxyPort());
            requestConfigBuilder.setProxy(proxy);

            CredentialsProvider credentialsProvider = new
BasicCredentialsProvider();

clientBuilder.setDefaultCredentialsProvider(credentialsProvider);

            if (getProxyUser() != null && getProxyPassword() != null) {
                credentialsProvider.setCredentials(
                    new AuthScope(getProxyHost(), getProxyPort()),
                    new UsernamePasswordCredentials(getProxyUser(),
getProxyPassword()));
            }

            if (System.getProperty("java.security.krb5.conf") != null) {
                 Lookup<AuthSchemeProvider> authSchemeRegistry =
RegistryBuilder.<AuthSchemeProvider>create()
                        .register(AuthSchemes.SPNEGO, new
SPNegoSchemeFactory())
                        .build();


                 credentialsProvider.setCredentials(
                         new AuthScope(getProxyHost(), getProxyPort(),
"Negotiate"),
                         new UsernamePasswordCredentials(getProxyUser(),
getProxyPassword()));


clientBuilder.setDefaultAuthSchemeRegistry(authSchemeRegistry);
                requestConfigBuilder.setTargetPreferredAuthSchemes(
                        Arrays.asList(AuthSchemes.NTLM,
AuthSchemes.KERBEROS, AuthSchemes.SPNEGO));
            }
        }

        requestConfigBuilder.setSocketTimeout(soTimeout);
        requestConfigBuilder.setCookieSpec(CookieSpecs.DEFAULT);
        clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());

        return clientBuilder.build();
    }

In essence, the client would need to provide a kerberos config file
via java.security.krb5.conf, and if they do, this code adds the SPNEGO
scheme and adds the credentials to the credentialsProvider for the
Negotiate scheme.

This seems to work for my specific case, but I'm happy to expand on it and
incorporate any feedback. I can add an integration test as well.

Does anyone have any thoughts? Are there any better approaches? Could I
submit a PR for this if its suitable?

Many thanks

Jon