Skip to content

Commit

Permalink
Merge pull request #6 from maheshp/add_verify_connection_support
Browse files Browse the repository at this point in the history
File base auth plugin supports verify_connection
  • Loading branch information
bdpiprava authored Apr 24, 2017
2 parents 272812d + 2130601 commit a140982
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 9 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
apply plugin: 'java'

group = 'cd.go'
version = '0.0.1'
version = '0.0.1-SNAPSHOT'

project.ext.pluginDesc = [
id : 'cd.go.authentication.passwordfile',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public GoPluginApiResponse handle(GoPluginApiRequest request) throws UnhandledRe
return new GetAuthConfigMetadataExecutor().execute();
case REQUEST_AUTH_CONFIG_VIEW:
return new GetAuthConfigViewExecutor().execute();
case REQUEST_VERIFY_CONNECTION:
return new VerifyConnectionRequestExecutor(request).execute();
case REQUEST_VALIDATE_AUTH_CONFIG:
return new AuthConfigValidateRequestExecutor(request).execute();
case REQUEST_AUTHENTICATE_USER:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ public GoPluginApiResponse execute() {
}

Capabilities getCapabilities() {
return new Capabilities(SupportedAuthType.Password, true, false, false);
return new Capabilities(SupportedAuthType.Password, true, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum RequestFromServer {
REQUEST_GET_AUTH_CONFIG_METADATA(String.join(".", Constants.REQUEST_PREFIX, Constants._AUTH_CONFIG_METADATA, "get-metadata")),
REQUEST_AUTH_CONFIG_VIEW(String.join(".", Constants.REQUEST_PREFIX, Constants._AUTH_CONFIG_METADATA, "get-view")),
REQUEST_VALIDATE_AUTH_CONFIG(String.join(".", Constants.REQUEST_PREFIX, Constants._AUTH_CONFIG_METADATA, "validate")),
REQUEST_VERIFY_CONNECTION(String.join(".", Constants.REQUEST_PREFIX, Constants._AUTH_CONFIG_METADATA, "verify-connection")),

REQUEST_AUTHENTICATE_USER(Constants.REQUEST_PREFIX + ".authenticate-user"),
REQUEST_SEARCH_USERS(Constants.REQUEST_PREFIX + ".search-users");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2017 ThoughtWorks, 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 cd.go.authentication.passwordfile.executor;


import cd.go.authentication.passwordfile.model.Configuration;
import com.google.gson.Gson;
import com.thoughtworks.go.plugin.api.request.GoPluginApiRequest;
import com.thoughtworks.go.plugin.api.response.DefaultGoPluginApiResponse;
import com.thoughtworks.go.plugin.api.response.GoPluginApiResponse;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.commons.lang3.StringUtils.isBlank;

public class VerifyConnectionRequestExecutor implements RequestExecutor {
private static final Gson GSON = new Gson();
private final GoPluginApiRequest request;

public VerifyConnectionRequestExecutor(GoPluginApiRequest request) {
this.request = request;
}

@Override
public GoPluginApiResponse execute() throws Exception {
List<Map<String, String>> errors = validateAuthConfig();
if (errors.size() != 0) {
return validationFailureResponse(errors);
}

VerifyConnectionResult result = verifyConnection();
if (!result.isSuccessful()) {
return verifyConnectionFailureResponse(result.getError());
}

return successResponse();
}

private VerifyConnectionResult verifyConnection() {
VerifyConnectionResult result = new VerifyConnectionResult();
Configuration configuration = Configuration.fromJSON(request.requestBody());
File file = new File(configuration.getPasswordFilePath());

try {
if(!file.exists()) {
result.setError(String.format("No password file at path `%s`.", configuration.getPasswordFilePath()));
return result;
}

if (!file.isFile()) {
result.setError(String.format("Password file path `%s` is not a normal file.", configuration.getPasswordFilePath()));
return result;
}

if (!file.canRead()) {
result.setError(String.format("Unable to read password file `%s`, check permissions."));
}
} catch (SecurityException e) {
result.setError(e.getMessage());
}

return result;
}

private List<Map<String, String>> validateAuthConfig() {
Map<String, String> configuration = GSON.fromJson(request.requestBody(), Map.class);

return Configuration.validate(configuration);
}

private GoPluginApiResponse successResponse() {
return respondWith("success", "Connection ok", null);
}

private GoPluginApiResponse verifyConnectionFailureResponse(String errorMessage) {
return respondWith("failure", errorMessage, null);
}

private GoPluginApiResponse validationFailureResponse(List<Map<String, String>> errors) {
return respondWith("validation-failed", "Validation failed for the given Auth Config", errors);
}

private GoPluginApiResponse respondWith(String status, String message, List<Map<String, String>> errors) {
HashMap<String, Object> response = new HashMap<>();
response.put("status", status);
response.put("message", message);

if (errors != null && errors.size() > 0) {
response.put("errors", errors);
}

return DefaultGoPluginApiResponse.success(GSON.toJson(response));
}

class VerifyConnectionResult {
private String error;

public boolean isSuccessful() {
return isBlank(error);
}

public void setError(String errorMessage) {
this.error = errorMessage;
}

public String getError() {
return this.error;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,14 @@ public class Capabilities {
@SerializedName("can_search")
private final boolean canSearch;

@Expose
@SerializedName("can_verify_connection")
private final boolean canVerifyConnection;

@Expose
@SerializedName("can_authorize")
private final boolean canAuthorize;


public Capabilities(SupportedAuthType supportedAuthType, boolean canSearch, boolean canVerifyConnection, boolean canAuthorize) {
public Capabilities(SupportedAuthType supportedAuthType, boolean canSearch, boolean canAuthorize) {
this.supportedAuthType = supportedAuthType;
this.canSearch = canSearch;
this.canVerifyConnection = canVerifyConnection;
this.canAuthorize = canAuthorize;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public void shouldExposeItsCapabilities() throws Exception {
String expectedJSON = "{\n" +
" \"supported_auth_type\":\"password\",\n" +
" \"can_search\":true,\n" +
" \"can_verify_connection\":false,\n" +
" \"can_authorize\":false\n" +
"}";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2017 ThoughtWorks, 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 cd.go.authentication.passwordfile.executor;

import com.thoughtworks.go.plugin.api.request.DefaultGoPluginApiRequest;
import com.thoughtworks.go.plugin.api.response.GoPluginApiResponse;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

public class VerifyConnectionRequestExecutorTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Test
public void execute_shouldValidateTheConfiguration() throws Exception {
DefaultGoPluginApiRequest request = new DefaultGoPluginApiRequest(null, null, null);
request.setRequestBody("{}");

GoPluginApiResponse response = new VerifyConnectionRequestExecutor(request).execute();

String expectedResponse = "{\"message\":\"Validation failed for the given Auth Config\",\"errors\":[{\"message\":\"PasswordFilePath must not be blank.\",\"key\":\"PasswordFilePath\"}],\"status\":\"validation-failed\"}";
assertThat(response.responseBody(), is(expectedResponse));
}

@Test
public void execute_shouldVerifyIfThePasswordFileExists() throws Exception {
DefaultGoPluginApiRequest request = new DefaultGoPluginApiRequest(null, null, null);
request.setRequestBody("{\"PasswordFilePath\": \"some_path\"}");

GoPluginApiResponse response = new VerifyConnectionRequestExecutor(request).execute();

String expectedResponse = "{\"message\":\"No password file at path `some_path`.\",\"status\":\"failure\"}";
assertThat(response.responseBody(), is(expectedResponse));
}

@Test
public void execute_shouldVerifyIfPasswordFilePathPointsToANormalFile() throws Exception {
File folder = this.folder.newFolder("subfolder");

DefaultGoPluginApiRequest request = new DefaultGoPluginApiRequest(null, null, null);
request.setRequestBody(String.format("{\"PasswordFilePath\": \"%s\"}", folder.getAbsolutePath()));

GoPluginApiResponse response = new VerifyConnectionRequestExecutor(request).execute();

String expectedResponse = String.format("{\"message\":\"Password file path `%s` is not a normal file.\",\"status\":\"failure\"}", folder.getAbsolutePath());
assertThat(response.responseBody(), is(expectedResponse));
}

@Test
public void execute_shouldReturnASuccessResponseIfValidationAndVerificationPasses() throws Exception {
File passwordFile = this.folder.newFile("password.properties");

DefaultGoPluginApiRequest request = new DefaultGoPluginApiRequest(null, null, null);
request.setRequestBody(String.format("{\"PasswordFilePath\": \"%s\"}", passwordFile.getAbsolutePath()));

GoPluginApiResponse response = new VerifyConnectionRequestExecutor(request).execute();

assertThat(response.responseBody(), is("{\"message\":\"Connection ok\",\"status\":\"success\"}"));
}
}

0 comments on commit a140982

Please sign in to comment.