--- /dev/null
+/*
+ * 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.platform;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public final class ServerId {
+ private final String id;
+ private final boolean valid;
+
+ public ServerId(String id, boolean valid) {
+ this.id = id;
+ this.valid = valid;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+}
package org.sonar.server.platform;
import com.google.common.collect.Lists;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.log.Loggers;
-
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.utils.log.Loggers;
/**
* @since 2.11
}
}
- public InetAddress toValidAddress(String ipAddress) {
+ private InetAddress toValidAddress(String ipAddress) {
if (StringUtils.isNotBlank(ipAddress)) {
List<InetAddress> validAddresses = getAvailableAddresses();
try {
--- /dev/null
+/*
+ * 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.platform;
+
+import com.google.common.base.Optional;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+
+import static com.google.common.base.Optional.fromNullable;
+
+public class ServerIdLoader {
+
+ private final Settings settings;
+ private final ServerIdGenerator idGenerator;
+
+ public ServerIdLoader(Settings settings, ServerIdGenerator idGenerator) {
+ this.settings = settings;
+ this.idGenerator = idGenerator;
+ }
+
+ public Optional<String> getRaw() {
+ return fromNullable(settings.getString(CoreProperties.PERMANENT_SERVER_ID));
+ }
+
+ public Optional<ServerId> get() {
+ Optional<String> rawId = getRaw();
+ if (!rawId.isPresent()) {
+ return Optional.absent();
+ }
+
+ String organisation = settings.getString(CoreProperties.ORGANISATION);
+ String ipAddress = settings.getString(CoreProperties.SERVER_ID_IP_ADDRESS);
+ boolean validated;
+ if (organisation == null || ipAddress == null) {
+ validated = false;
+ } else {
+ String generatedId = idGenerator.generate(organisation, ipAddress);
+ validated = generatedId != null && generatedId.equals(rawId.get());
+ }
+ return Optional.of(new ServerId(rawId.get(), validated));
+ }
+}
import com.google.common.base.Function;
import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import java.io.File;
import java.util.LinkedHashMap;
import org.sonar.api.server.authentication.IdentityProvider;
import org.sonar.process.ProcessProperties;
import org.sonar.server.authentication.IdentityProviderRepository;
+import org.sonar.server.platform.ServerId;
+import org.sonar.server.platform.ServerIdLoader;
import org.sonar.server.platform.ServerLogging;
import org.sonar.server.user.SecurityRealmFactory;
private final IdentityProviderRepository identityProviderRepository;
private final Server server;
private final ServerLogging serverLogging;
+ private final ServerIdLoader serverIdLoader;
public SonarQubeMonitor(Settings settings, SecurityRealmFactory securityRealmFactory,
- IdentityProviderRepository identityProviderRepository, Server server, ServerLogging serverLogging) {
+ IdentityProviderRepository identityProviderRepository, Server server, ServerLogging serverLogging,
+ ServerIdLoader serverIdLoader) {
this.settings = settings;
this.securityRealmFactory = securityRealmFactory;
this.identityProviderRepository = identityProviderRepository;
this.server = server;
this.serverLogging = serverLogging;
+ this.serverIdLoader = serverIdLoader;
}
@Override
public String getServerId() {
- return settings.getString(CoreProperties.PERMANENT_SERVER_ID);
+ return serverIdLoader.getRaw().orNull();
}
@Override
@Override
public Map<String, Object> attributes() {
Map<String, Object> attributes = new LinkedHashMap<>();
- attributes.put("Server ID", getServerId());
+ completeWithServerIdAttributes(attributes);
attributes.put("Version", getVersion());
addIfNotNull("External User Authentication", getExternalUserAuthentication(), attributes);
addIfNotEmpty("Accepted external identity providers", getEnabledIdentityProviders(), attributes);
return attributes;
}
+ private void completeWithServerIdAttributes(Map<String, Object> attributes) {
+ Optional<ServerId> serverId = serverIdLoader.get();
+ if (serverId.isPresent()) {
+ attributes.put("Server ID", serverId.get().getId());
+ attributes.put("Server ID validated", serverId.get().isValid());
+ }
+ }
+
private static void addIfNotNull(String key, @Nullable String value, Map<String, Object> attributes) {
if (value != null) {
attributes.put(key, value);
*/
package org.sonar.server.platform.monitoring;
+import javax.annotation.CheckForNull;
+
public interface SonarQubeMonitorMBean {
+ @CheckForNull
String getServerId();
String getVersion();
import org.sonar.server.db.CheckDatabaseCharsetAfterMigration;
import org.sonar.server.platform.PersistentSettings;
import org.sonar.server.platform.ServerIdGenerator;
+import org.sonar.server.platform.ServerIdLoader;
import org.sonar.server.startup.ServerMetadataPersister;
public class PlatformLevel3 extends PlatformLevel {
ServerMetadataPersister.class,
DefaultHttpDownloader.class,
UriReader.class,
+ ServerIdLoader.class,
ServerIdGenerator.class);
}
}
--- /dev/null
+/*
+ * 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.platform;
+
+import com.google.common.base.Optional;
+import org.junit.Test;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class ServerIdLoaderTest {
+
+ private static final String AN_ID = "ABC";
+ private static final String AN_IP = "1.2.3.4";
+ public static final String AN_ORGANISATION = "corp";
+
+ Settings settings = new Settings();
+ ServerIdGenerator idGenerator = mock(ServerIdGenerator.class);
+ ServerIdLoader underTest = new ServerIdLoader(settings, idGenerator);
+
+ @Test
+ public void get_returns_absent_if_id_property_is_not_set() {
+ settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+ settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+
+ Optional<ServerId> serverIdOpt = underTest.get();
+ assertThat(serverIdOpt.isPresent()).isFalse();
+ verifyZeroInteractions(idGenerator);
+ }
+
+ @Test
+ public void get_returns_valid_id() {
+ settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+ settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+ settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+ when(idGenerator.generate(AN_ORGANISATION, AN_IP)).thenReturn(AN_ID);
+
+ Optional<ServerId> serverIdOpt = underTest.get();
+ verifyServerId(serverIdOpt.get(), AN_ID, true);
+ verify(idGenerator).generate(AN_ORGANISATION, AN_IP);
+ }
+
+ @Test
+ public void get_returns_invalid_id_if_id_cant_be_generated_because_missing_organisation() {
+ settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+ settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+
+ Optional<ServerId> serverIdOpt = underTest.get();
+
+ verifyServerId(serverIdOpt.get(), AN_ID, false);
+ }
+
+ @Test
+ public void get_returns_invalid_id_if_id_cant_be_generated_because_missing_ip() {
+ settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+ settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+
+ Optional<ServerId> serverIdOpt = underTest.get();
+
+ verifyServerId(serverIdOpt.get(), AN_ID, false);
+ verifyZeroInteractions(idGenerator);
+ }
+
+ @Test
+ public void get_returns_invalid_id_if_id_cant_be_generated_because_missing_ip_and_organisation() {
+ settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+
+ Optional<ServerId> serverIdOpt = underTest.get();
+
+ verifyServerId(serverIdOpt.get(), AN_ID, false);
+ verifyZeroInteractions(idGenerator);
+ }
+
+ @Test
+ public void get_returns_invalid_id_if_input_is_different_than_newly_generated_id() {
+ settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+ settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+ settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+ when(idGenerator.generate(AN_ORGANISATION, AN_IP)).thenReturn("OTHER");
+
+ Optional<ServerId> serverIdOpt = underTest.get();
+
+ verifyServerId(serverIdOpt.get(), AN_ID, false);
+ verify(idGenerator).generate(AN_ORGANISATION, AN_IP);
+ }
+
+ @Test
+ public void getRaw_loads_id_from_settings() {
+ assertThat(underTest.getRaw().isPresent()).isFalse();
+
+ settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+ assertThat(underTest.getRaw().isPresent()).isTrue();
+ }
+
+ private static void verifyServerId(ServerId serverId, String expectedId, boolean expectedValid) {
+ assertThat(serverId.getId()).isEqualTo(expectedId);
+ assertThat(serverId.isValid()).isEqualTo(expectedValid);
+ }
+}
*/
package org.sonar.server.platform.monitoring;
+import com.google.common.base.Optional;
import java.io.File;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
import org.sonar.api.security.SecurityRealm;
-import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.server.authentication.IdentityProviderRepositoryRule;
import org.sonar.server.authentication.TestIdentityProvider;
+import org.sonar.server.platform.ServerId;
+import org.sonar.server.platform.ServerIdLoader;
import org.sonar.server.platform.ServerLogging;
import org.sonar.server.user.SecurityRealmFactory;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.data.MapEntry.entry;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SonarQubeMonitorTest {
+ private static final String SERVER_ID_PROPERTY = "Server ID";
+ private static final String SERVER_ID_VALIDATED_PROPERTY = "Server ID validated";
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
Settings settings = new Settings();
Server server = mock(Server.class);
+ ServerIdLoader serverIdLoader = mock(ServerIdLoader.class, RETURNS_DEEP_STUBS);
ServerLogging serverLogging = mock(ServerLogging.class);
SecurityRealmFactory securityRealmFactory = mock(SecurityRealmFactory.class);
- SonarQubeMonitor underTest = new SonarQubeMonitor(settings, securityRealmFactory, identityProviderRepository, server, serverLogging);
+ SonarQubeMonitor underTest = new SonarQubeMonitor(settings, securityRealmFactory, identityProviderRepository, server,
+ serverLogging, serverIdLoader);
@Before
public void setUp() throws Exception {
}
@Test
- public void getServerId() {
- when(server.getStartedAt()).thenReturn(DateUtils.parseDate("2015-01-01"));
+ public void test_getServerId() {
+ when(serverIdLoader.getRaw()).thenReturn(Optional.of("ABC"));
+ assertThat(underTest.getServerId()).isEqualTo("ABC");
+
+ when(serverIdLoader.getRaw()).thenReturn(Optional.<String>absent());
+ assertThat(underTest.getServerId()).isNull();
+ }
+
+ @Test
+ public void attributes_contain_information_about_valid_server_id() {
+ when(serverIdLoader.get()).thenReturn(Optional.of(new ServerId("ABC", true)));
+
+ Map<String, Object> attributes = underTest.attributes();
+ assertThat(attributes).contains(entry(SERVER_ID_PROPERTY, "ABC"), entry(SERVER_ID_VALIDATED_PROPERTY, true));
+ }
+
+ @Test
+ public void attributes_contain_information_about_non_valid_server_id() {
+ when(serverIdLoader.get()).thenReturn(Optional.of(new ServerId("ABC", false)));
+
+ Map<String, Object> attributes = underTest.attributes();
+ assertThat(attributes).contains(entry(SERVER_ID_PROPERTY, "ABC"), entry(SERVER_ID_VALIDATED_PROPERTY, false));
+ }
+
+ @Test
+ public void attributes_do_not_contain_information_about_server_id_if_absent() {
+ when(serverIdLoader.get()).thenReturn(Optional.<ServerId>absent());
Map<String, Object> attributes = underTest.attributes();
- assertThat(attributes).containsKeys("Server ID", "Version");
+ assertThat(attributes).doesNotContainKeys(SERVER_ID_PROPERTY, SERVER_ID_VALIDATED_PROPERTY);
}
@Test
public void jdbc_password_property_has_password_type() {
List<PropertyDefinition> defs = CorePropertyDefinitions.all();
Optional<PropertyDefinition> prop = from(defs).filter(new HasKeyPredicate(DatabaseProperties.PROP_PASSWORD)).first();
- assertThat(prop.isPresent()).isTrue();
assertThat(prop.get().type()).isEqualTo(PropertyType.PASSWORD);
}