* Save external password only if enabled "sonar.security.savePassword".
* Bypass restriction on password length (4), when external system enabled.
* Improve error handling.
// SERVER-SIDE TECHNICAL PROPERTIES
+ @Property(
+ key = "sonar.security.realm",
+ name = "Security Realm",
+ project = false,
+ global = false
+ ),
+ @Property(
+ key = "sonar.security.savePassword",
+ name = "Save external password",
+ project = false,
+ global = false
+ ),
@Property(
key = "sonar.authenticator.downcase",
name = "Downcase login",
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.ui;
-
-/**
- * @deprecated in 2.14 and should be removed
- */
-@Deprecated
-public class AuthenticatorNotFoundException extends RuntimeException {
-
- public AuthenticatorNotFoundException(String classname) {
- super(classname);
- }
-}
import org.sonar.api.config.Settings;
import org.sonar.api.security.LoginPasswordAuthenticator;
import org.sonar.api.security.SecurityRealm;
+import org.sonar.api.utils.SonarException;
/**
* @since 2.14
public class SecurityRealmFactory implements ServerComponent {
private static final Logger INFO = LoggerFactory.getLogger("org.sonar.INFO");
- private static final Logger LOG = LoggerFactory.getLogger(SecurityRealmFactory.class);
private final boolean ignoreStartupFailure;
private final SecurityRealm realm;
if (!StringUtils.isEmpty(realmName)) {
selectedRealm = selectRealm(realms, realmName);
if (selectedRealm == null) {
- LOG.error("Realm not found. Please check the property '" + REALM_PROPERTY + "' in conf/sonar.properties");
- throw new AuthenticatorNotFoundException(realmName);
+ throw new SonarException("Realm '" + realmName + "' not found. Please check the property '" + REALM_PROPERTY + "' in conf/sonar.properties");
}
}
if (selectedRealm == null && !StringUtils.isEmpty(className)) {
LoginPasswordAuthenticator authenticator = selectAuthenticator(authenticators, className);
if (authenticator == null) {
- LOG.error("Authenticator plugin not found. Please check the property '" + CoreProperties.CORE_AUTHENTICATOR_CLASS
+ throw new SonarException("Authenticator '" + className + "' not found. Please check the property '" + CoreProperties.CORE_AUTHENTICATOR_CLASS
+ "' in conf/sonar.properties");
- throw new AuthenticatorNotFoundException(className);
}
selectedRealm = new CompatibilityRealm(authenticator);
}
INFO.info("Security realm started");
} catch (RuntimeException e) {
if (ignoreStartupFailure) {
- LOG.error("IGNORED - Realm fails to start: " + e.getMessage());
+ INFO.error("IGNORED - Security realm fails to start: " + e.getMessage());
} else {
- LOG.error("Realm fails to start: " + e.getMessage());
- throw e;
+ throw new SonarException("Security realm fails to start: " + e.getMessage(), e);
}
}
}
@java_authenticator = java_realm.getLoginPasswordAuthenticator()
@java_users_provider = java_realm.getUsersProvider()
@java_groups_provider = java_realm.getGroupsProvider()
+
+ @save_password = Java::OrgSonarServerUi::JRubyFacade.new.getSettings().getBoolean('sonar.security.savePassword')
end
def authenticate?(username, password)
details = @java_users_provider.doGetUserDetails(username)
rescue Exception => e
Rails.logger.error("Error from external users provider: #{e.message}")
+ return false if !@save_password
return fallback(username, password)
else
# User exist in external system
- auth(username, password, details) if details
+ return auth(username, password, details) if details
# No such user in external system
return fallback(username, password)
end
java_facade = Java::OrgSonarServerUi::JRubyFacade.new
return nil if !java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
# Automatically create a user in the sonar db if authentication has been successfully done
- user = User.new(:login => username, :name => username, :email => '', :password => password, :password_confirmation => password)
+ user = User.new(:login => username, :name => username, :email => '')
default_group_name = java_facade.getSettings().getString('sonar.defaultGroup')
default_group = Group.find_by_name(default_group_name)
if default_group
end
end
if details
- user.update_attributes(:name => details.getName(), :email => details.getEmail())
+ user.name = details.getName()
+ user.email = details.getEmail()
+ end
+ if @save_password
+ user.password = password
+ user.password_confirmation = password
end
- user.update_attributes(:password => password, :password_confirmation => password)
synchronize_groups(user)
- user.save
+ # Note that validation disabled
+ user.save(false)
return user
end
import org.sonar.api.config.Settings;
import org.sonar.api.security.LoginPasswordAuthenticator;
import org.sonar.api.security.SecurityRealm;
+import org.sonar.api.utils.SonarException;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
assertThat(factory.getRealm(), nullValue());
}
- @Test(expected = AuthenticatorNotFoundException.class)
+ @Test
public void realmNotFound() {
settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, "Fake");
- new SecurityRealmFactory(settings);
+ try {
+ new SecurityRealmFactory(settings);
+ fail();
+ } catch (SonarException e) {
+ assertThat(e.getMessage(), containsString("Realm 'Fake' not found."));
+ }
}
@Test
assertThat(factory.getRealm(), is(realm));
}
- @Test(expected = AuthenticatorNotFoundException.class)
+ @Test
public void authenticatorNotFound() {
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "Fake");
- new SecurityRealmFactory(settings);
+ try {
+ new SecurityRealmFactory(settings);
+ fail();
+ } catch (SonarException e) {
+ assertThat(e.getMessage(), containsString("Authenticator 'Fake' not found."));
+ }
}
@Test
verify(realm).init();
}
- @Test(expected = IllegalStateException.class)
+ @Test
public void shouldFail() {
SecurityRealm realm = spy(new AlwaysFailsRealm());
settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, realm.getName());
- new SecurityRealmFactory(settings, new SecurityRealm[] {realm}).start();
+ try {
+ new SecurityRealmFactory(settings, new SecurityRealm[] {realm}).start();
+ fail();
+ } catch (SonarException e) {
+ assertThat(e.getCause(), instanceOf(IllegalStateException.class));
+ assertThat(e.getMessage(), containsString("Security realm fails to start"));
+ }
}
private static class AlwaysFailsRealm extends FakeRealm {