瀏覽代碼

SONAR-7982 Create WS api/settings/encrypt to encrypt a setting value

tags/6.1-RC1
Teryk Bellahsene 7 年之前
父節點
當前提交
04c4e788e1

+ 75
- 0
server/sonar-server/src/main/java/org/sonar/server/setting/ws/EncryptAction.java 查看文件

@@ -0,0 +1,75 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.setting.ws;

import org.sonar.api.config.Settings;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Settings.EncryptWsResponse;

import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_VALUE;

public class EncryptAction implements SettingsWsAction {
private final UserSession userSession;
private final Settings settings;

public EncryptAction(UserSession userSession, Settings settings) {
this.userSession = userSession;
this.settings = settings;
}

@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("encrypt")
.setDescription("Encrypt a setting value.<br>" +
"Requires 'Administer System' permission.")
.setSince("6.1")
.setHandler(this)
.setInternal(true)
.setResponseExample(getClass().getResource("encrypt-example.json"));

action.createParam(PARAM_VALUE)
.setRequired(true)
.setDescription("Setting value to encrypt")
.setExampleValue("my value");
}

@Override
public void handle(Request request, Response response) throws Exception {
userSession.checkPermission(SYSTEM_ADMIN);

String value = request.mandatoryParam(PARAM_VALUE);
checkRequest(!value.isEmpty(), "Parameter '%s' must not be empty", PARAM_VALUE);

String encryptedValue = settings.getEncryption().encrypt(value);

writeProtobuf(toEncryptWsResponse(encryptedValue), request, response);
}

private static EncryptWsResponse toEncryptWsResponse(String encryptedValue) {
return EncryptWsResponse.newBuilder().setEncryptedValue(encryptedValue).build();
}
}

+ 1
- 0
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWsModule.java 查看文件

@@ -32,6 +32,7 @@ public class SettingsWsModule extends Module {
ValuesAction.class,
SettingsFinder.class,
ResetAction.class,
EncryptAction.class,
SettingsUpdater.class);
}
}

+ 3
- 0
server/sonar-server/src/main/resources/org/sonar/server/setting/ws/encrypt-example.json 查看文件

@@ -0,0 +1,3 @@
{
"encryptedValue": "{aes}q2ANI9ikR9R8P2CMCCTWeA=="
}

+ 146
- 0
server/sonar-server/src/test/java/org/sonar/server/setting/ws/EncryptActionTest.java 查看文件

@@ -0,0 +1,146 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.setting.ws;

import com.google.common.base.Throwables;
import java.io.File;
import java.io.IOException;
import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.config.Encryption;
import org.sonar.api.config.Settings;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.Settings.EncryptWsResponse;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_VALUE;

public class EncryptActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public UserSessionRule userSession = UserSessionRule.standalone().setGlobalPermissions(SYSTEM_ADMIN);
@Rule
public TemporaryFolder folder = new TemporaryFolder();

Settings settings = mock(Settings.class);
Encryption encryption;

EncryptAction underTest = new EncryptAction(userSession, settings);

WsActionTester ws = new WsActionTester(underTest);

@Before
public void setUp_secret_key() {
try {
File secretKeyFile = folder.newFile();
FileUtils.writeStringToFile(secretKeyFile, "fCVFf/JHRi8Qwu5KLNva7g==");

encryption = new Encryption(secretKeyFile.getAbsolutePath());

when(settings.getEncryption()).thenReturn(encryption);
} catch (IOException e) {
Throwables.propagate(e);
}
}

@Test
public void json_example() {
String result = ws.newRequest().setParam("value", "my value").execute().getInput();

assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
}

@Test
public void encrypt() {
EncryptWsResponse result = call("my value!");

assertThat(result.getEncryptedValue()).isEqualTo("{aes}NoofntibpMBdhkMfXQxYcA==");
}

@Test
public void definition() {
WebService.Action definition = ws.getDef();

assertThat(definition.key()).isEqualTo("encrypt");
assertThat(definition.isPost()).isFalse();
assertThat(definition.isInternal()).isTrue();
assertThat(definition.responseExampleAsString()).isNotEmpty();
assertThat(definition.params()).hasSize(1);

}

@Test
public void fail_if_insufficient_permissions() {
expectedException.expect(ForbiddenException.class);

userSession.anonymous().setGlobalPermissions(QUALITY_PROFILE_ADMIN);

call("my value");
}

@Test
public void fail_if_value_is_not_provided() {
expectedException.expect(IllegalArgumentException.class);

call(null);
}

@Test
public void fail_if_value_is_empty() {
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Parameter 'value' must not be empty");

call(" ");
}

private EncryptWsResponse call(@Nullable String value) {
TestRequest request = ws.newRequest()
.setMediaType(MediaTypes.PROTOBUF)
.setMethod("POST");

if (value != null) {
request.setParam(PARAM_VALUE, value);
}

try {
return EncryptWsResponse.parseFrom(request.execute().getInputStream());
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/setting/ws/SettingsWsModuleTest.java 查看文件

@@ -29,6 +29,6 @@ public class SettingsWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new SettingsWsModule().configure(container);
assertThat(container.size()).isEqualTo(8 + 2);
assertThat(container.size()).isEqualTo(9 + 2);
}
}

+ 5
- 0
sonar-ws/src/main/protobuf/ws-settings.proto 查看文件

@@ -29,6 +29,11 @@ message ListDefinitionsWsResponse {
repeated Definition definitions = 1;
}

// Response of GET api/settings/encrypt
message EncryptWsResponse {
optional string encryptedValue = 1;
}

message Definition {
optional string key = 1;
optional string name = 2;

Loading…
取消
儲存