changeset 2739:cc16bcb56e60

Use BASIC authentication as fallback. Reviewed-by: jkang Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024650.html
author Severin Gehwolf <sgehwolf@redhat.com>
date Wed, 23 Aug 2017 13:51:09 +0200
parents 7815245e7915
children 3d1c63f2b665
files agent/core/src/main/java/com/redhat/thermostat/agent/http/HttpRequestService.java agent/core/src/test/java/com/redhat/thermostat/agent/http/HttpRequestServiceTest.java
diffstat 2 files changed, 85 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/http/HttpRequestService.java	Wed Aug 23 11:14:49 2017 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/http/HttpRequestService.java	Wed Aug 23 13:51:09 2017 +0200
@@ -52,6 +52,7 @@
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.client.util.StringContentProvider;
+import org.eclipse.jetty.http.HttpHeader;
 import org.eclipse.jetty.http.HttpMethod;
 import org.eclipse.jetty.http.HttpStatus;
 
@@ -63,6 +64,8 @@
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.config.SSLConfiguration;
+import com.redhat.thermostat.storage.config.FileStorageCredentials;
+import com.redhat.thermostat.storage.core.StorageCredentials;
 
 @Component
 @Service(value = HttpRequestService.class)
@@ -70,28 +73,32 @@
     
     private static final Logger logger = LoggingUtils.getLogger(HttpRequestService.class);
 
+    private static final String UNKNOWN_CREDS = "UNKNOWN:UNKNOWN";
     private static final String KEYCLOAK_TOKEN_SERVICE = "/auth/realms/__REALM__/protocol/openid-connect/token";
     private static final String KEYCLOAK_CONTENT_TYPE = "application/x-www-form-urlencoded";
 
+    private final CredentialsCreator credsCreator; // Used for BASIC auth
     private final HttpClientCreator httpClientCreator;
     private final ConfigCreator configCreator;
     private Gson gson = new GsonBuilder().create();
     private HttpClientFacade client;
     private AgentStartupConfiguration agentStartupConfiguration;
-
+    private StorageCredentials creds; // Used for BASIC auth
     private KeycloakAccessToken keycloakAccessToken;
+    
     @Reference
     private SSLConfiguration sslConfig;
     @Reference
     private CommonPaths commonPaths;
 
     public HttpRequestService() {
-        this(new HttpClientCreator(), new ConfigCreator());
+        this(new HttpClientCreator(), new ConfigCreator(), new CredentialsCreator());
     }
 
-    HttpRequestService(HttpClientCreator clientCreator, ConfigCreator configCreator) {
+    HttpRequestService(HttpClientCreator clientCreator, ConfigCreator configCreator, CredentialsCreator credsCreator) {
         this.httpClientCreator = clientCreator;
         this.configCreator = configCreator;
+        this.credsCreator = credsCreator;
     }
 
     @Activate
@@ -99,6 +106,7 @@
         try {
             agentStartupConfiguration = configCreator.create(commonPaths);
             client = httpClientCreator.create(sslConfig);
+            creds = credsCreator.create(commonPaths);
             client.start();
             logger.log(Level.FINE, "HttpRequestService activated");
         } catch (Exception e) {
@@ -124,7 +132,10 @@
 
         try {
             if (agentStartupConfiguration.isKeycloakEnabled()) {
-                request.header("Authorization", "Bearer " + getAccessToken());
+                request.header(HttpHeader.AUTHORIZATION.asString(), "Bearer " + getAccessToken());
+            } else {
+                request.header(HttpHeader.AUTHORIZATION.asString(),
+                               getBasicAuthHeaderValue());
             }
             ContentResponse response =  request.send();
             int status = response.getStatus();
@@ -210,9 +221,27 @@
         return "grant_type=refresh_token&client_id=" + agentStartupConfiguration.getKeycloakClient() +
                 "&refresh_token=" + keycloakAccessToken.getRefreshToken();
     }
+    
+    String getBasicAuthHeaderValue() {
+        String username = creds.getUsername();
+        char[] pwdChar = creds.getPassword();
+        String userpassword;
+        if (username == null || username.isEmpty() || pwdChar == null) {
+            logger.warning("No credentials specified in " + commonPaths.getUserAgentAuthConfigFile() + ". The connection will fail.");
+            userpassword = UNKNOWN_CREDS;
+        } else {
+            String pwd = new String(pwdChar);
+            userpassword = username + ":" + pwd;
+        }
+        
+        @SuppressWarnings("restriction")
+        String encodedAuthorization = new sun.misc.BASE64Encoder()
+                .encode(userpassword.getBytes());
+        return "Basic " + encodedAuthorization;
+    }
 
     // Package-private for testing
-   void setConfiguration(AgentStartupConfiguration configuration) {
+    void setConfiguration(AgentStartupConfiguration configuration) {
         this.agentStartupConfiguration = configuration;
     }
 
@@ -232,6 +261,12 @@
         }
     }
     
+    static class CredentialsCreator {
+        StorageCredentials create(CommonPaths paths) {
+            return new FileStorageCredentials(paths.getUserAgentAuthConfigFile());
+        }
+    }
+    
     @SuppressWarnings("serial")
     public static class RequestFailedException extends Exception {
         
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/http/HttpRequestServiceTest.java	Wed Aug 23 11:14:49 2017 -0400
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/http/HttpRequestServiceTest.java	Wed Aug 23 13:51:09 2017 +0200
@@ -38,6 +38,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -64,10 +65,14 @@
 
 import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
 import com.redhat.thermostat.agent.http.HttpRequestService.ConfigCreator;
+import com.redhat.thermostat.agent.http.HttpRequestService.CredentialsCreator;
 import com.redhat.thermostat.agent.http.HttpRequestService.HttpClientCreator;
 import com.redhat.thermostat.agent.http.HttpRequestService.RequestFailedException;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.config.SSLConfiguration;
+import com.redhat.thermostat.storage.core.StorageCredentials;
+
+import org.eclipse.jetty.http.HttpHeader;
 import org.eclipse.jetty.http.HttpMethod;
 
 public class HttpRequestServiceTest {
@@ -75,9 +80,12 @@
     private static final URI GET_URI = GATEWAY_URI.resolve("?q=foo&l=3");
     private static final String payload = "{}";
     private static final String keycloakUrl = "http://127.0.0.1:31000/keycloak";
+    private static final char[] BASIC_PASSWORD = new char[] { 'p', 'a', 's', 's' };
+    private static final String BASIC_USERNAME = "testing";
 
     private HttpClientCreator clientCreator;
     private ConfigCreator configCreator;
+    private CredentialsCreator credsCreator;
     private HttpClientFacade client;
     private Request httpRequest;
     
@@ -92,6 +100,11 @@
         clientCreator = mock(HttpClientCreator.class);
         when(clientCreator.create(any(SSLConfiguration.class))).thenReturn(client);
         configCreator = mock(ConfigCreator.class);
+        credsCreator = mock(CredentialsCreator.class);
+        StorageCredentials creds = mock(StorageCredentials.class);
+        when(creds.getPassword()).thenReturn(BASIC_PASSWORD);
+        when(creds.getUsername()).thenReturn(BASIC_USERNAME);
+        when(credsCreator.create(any(CommonPaths.class))).thenReturn(creds);
     }
 
     @Test
@@ -179,9 +192,38 @@
         verify(httpRequest).send();
     }
     
+    @Test
+    public void verifyNoKeycloakDefaultsToAuthBasic() throws Exception {
+        AgentStartupConfiguration configuration = createNoKeycloakConfig();
+
+        HttpRequestService service = createAndActivateRequestService(configuration);
+
+        service.sendHttpRequest(null, GATEWAY_URI, com.redhat.thermostat.agent.http.HttpRequestService.Method.GET);
+
+        verify(client).newRequest(GATEWAY_URI);
+        verify(configuration).isKeycloakEnabled();
+
+        ArgumentCaptor<String> authValueCaptor = ArgumentCaptor.forClass(String.class);
+        verify(httpRequest).header(eq(HttpHeader.AUTHORIZATION.asString()), authValueCaptor.capture());
+        String authValueEncoded = authValueCaptor.getValue();
+        assertTrue(authValueEncoded.startsWith("Basic "));
+        String userPassEncoded = authValueEncoded.substring("Basic ".length());
+        String decodedUserPass = getDecodedUserPass(userPassEncoded);
+        String expectedCreds = BASIC_USERNAME + ":" + new String(BASIC_PASSWORD);
+        assertEquals(expectedCreds, decodedUserPass);
+        verify(httpRequest).method(eq(HttpMethod.GET));
+        verify(httpRequest).send();
+    }
+    
+    private String getDecodedUserPass(String userPassEncoded) throws IOException {
+        @SuppressWarnings("restriction")
+        byte[] decodedBytes = new sun.misc.BASE64Decoder().decodeBuffer(userPassEncoded);
+        return new String(decodedBytes);
+    }
+
     private HttpRequestService createAndActivateRequestService(AgentStartupConfiguration configuration) throws Exception {
         when(configCreator.create(any(CommonPaths.class))).thenReturn(configuration);
-        HttpRequestService service = new HttpRequestService(clientCreator, configCreator);
+        HttpRequestService service = new HttpRequestService(clientCreator, configCreator, credsCreator);
         service.activate();
         verify(client).start();
         return service;
@@ -196,7 +238,7 @@
         AgentStartupConfiguration configuration = createNoKeycloakConfig();
         ConfigCreator configCreator = mock(ConfigCreator.class);
         when(configCreator.create(any(CommonPaths.class))).thenReturn(configuration);
-        HttpRequestService service = new HttpRequestService(creator, configCreator);
+        HttpRequestService service = new HttpRequestService(creator, configCreator, credsCreator);
         service.activate();
         String content = service.sendHttpRequest(null, GET_URI, com.redhat.thermostat.agent.http.HttpRequestService.Method.GET);
         verify(getClient).newRequest(GET_URI);
@@ -212,7 +254,7 @@
         AgentStartupConfiguration configuration = createNoKeycloakConfig();
         ConfigCreator configCreator = mock(ConfigCreator.class);
         when(configCreator.create(any(CommonPaths.class))).thenReturn(configuration);
-        HttpRequestService service = new HttpRequestService(creator, configCreator);
+        HttpRequestService service = new HttpRequestService(creator, configCreator, credsCreator);
         service.activate();
         
         // Add extra slashes to URI