Skip to content

Commit

Permalink
Add interceptor that requests oauth token from openshift (if needed) …
Browse files Browse the repository at this point in the history
…using username/password.
  • Loading branch information
iocanel committed Nov 9, 2015
1 parent ac51bfe commit a926786
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
import io.fabric8.kubernetes.client.dsl.ClientNonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.ClientResource;
import io.fabric8.kubernetes.client.dsl.ClientRollableScallableResource;
import io.fabric8.kubernetes.client.dsl.base.BaseOperation;
import io.fabric8.kubernetes.client.dsl.base.OperationSupport;
import io.fabric8.openshift.api.model.Build;
import io.fabric8.openshift.api.model.BuildConfig;
import io.fabric8.openshift.api.model.BuildConfigList;
Expand Down Expand Up @@ -135,6 +137,7 @@
import io.fabric8.openshift.client.dsl.internal.RouteOperationsImpl;
import io.fabric8.openshift.client.dsl.internal.TemplateOperationsImpl;
import io.fabric8.openshift.client.dsl.internal.UserOperationsImpl;
import io.fabric8.openshift.client.internal.OpenShiftOAuthInterceptor;

import java.net.MalformedURLException;
import java.net.URL;
Expand All @@ -155,6 +158,7 @@ public DefaultOpenShiftClient(final Config config) throws KubernetesClientExcept
public DefaultOpenShiftClient(final OpenShiftConfig config) throws KubernetesClientException {
super(config);
try {
addOpenShiftAuthInterceptor();
this.delegate = new DefaultKubernetesClient(httpClient, config);
this.openShiftUrl = new URL(config.getOpenShiftUrl());
} catch (MalformedURLException e) {
Expand All @@ -169,13 +173,19 @@ public DefaultOpenShiftClient(String masterUrl) throws KubernetesClientException
private DefaultOpenShiftClient(OkHttpClient httpClient, OpenShiftConfig config) throws KubernetesClientException {
super(httpClient, config);
try {
addOpenShiftAuthInterceptor();
this.delegate = new DefaultKubernetesClient(httpClient, config);
this.openShiftUrl = new URL(config.getOpenShiftUrl());
} catch (MalformedURLException e) {
throw new KubernetesClientException("Could not create client", e);
}
}

private void addOpenShiftAuthInterceptor() {
httpClient.setAuthenticator(null);
httpClient.interceptors().add(new OpenShiftOAuthInterceptor(httpClient, OpenShiftConfig.wrap(getConfiguration())));
}

@Override
public URL getOpenshiftUrl() {
return openShiftUrl;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright (C) 2015 Red Hat, 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 io.fabric8.openshift.client.internal;

import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.utils.URLUtils;
import io.fabric8.kubernetes.client.utils.Utils;
import io.fabric8.openshift.client.OpenShiftConfig;

import java.io.IOException;
import java.net.URL;
import java.util.concurrent.atomic.AtomicReference;

public class OpenShiftOAuthInterceptor implements Interceptor {

private static final String AUTHORIZATION = "Authorization";
private static final String LOCATION = "Location";
private static final String AUTHORIZE_PATH = "oauth/authorize?response_type=token&client_id=openshift-challenging-client";

private static final String BEFORE_TOKEN = "access_token=";
private static final String AFTER_TOKEN = "&expires";

private final OkHttpClient client;
private final OpenShiftConfig config;
private final AtomicReference<String> oauthToken = new AtomicReference<>();

public OpenShiftOAuthInterceptor(OkHttpClient client, OpenShiftConfig config) {
this.client = client;
this.config = config;
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();

//Build new request
Request.Builder builder = request.newBuilder();
builder.header("Accept", "application/json");

String token = oauthToken.get();
if (Utils.isNotNullOrEmpty(token)) {
setAuthHeader(builder, token);
}

request = builder.build();
Response response = chain.proceed(request);

if (response.code() == 401 || response.code() == 403) {
synchronized (client) {
token = authorize();
if(token != null) {
oauthToken.set(token);
setAuthHeader(builder, token);
request = builder.build();
return chain.proceed(request); //repeat request with new token
}
}
}
return response;
}

private void setAuthHeader(Request.Builder builder, String token) {
if (token != null) {
builder.header(AUTHORIZATION, String.format("Bearer %s", token));
}
}

private String authorize() {
try {
OkHttpClient clone = client.clone();
clone.interceptors().remove(this);

String credential = Credentials.basic(config.getUsername(), new String(config.getPassword()));
URL url = new URL(URLUtils.join(config.getMasterUrl(), AUTHORIZE_PATH));
Response response = clone.newCall(new Request.Builder().get().url(url).header(AUTHORIZATION, credential).build()).execute();
String token = response.priorResponse().networkResponse().header(LOCATION);
token = token.substring(token.indexOf(BEFORE_TOKEN) + BEFORE_TOKEN.length());
token = token.substring(0, token.indexOf(AFTER_TOKEN));
return token;
} catch (Exception e) {
throw KubernetesClientException.launderThrowable(e);
}
}
}

0 comments on commit a926786

Please sign in to comment.