Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Azure Regions #47

Merged
merged 3 commits into from
Sep 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,8 @@

import static java.lang.String.format;
import static org.almrangers.auth.aad.AadSettings.AUTH_REQUEST_FORMAT;
import static org.almrangers.auth.aad.AadSettings.GROUPS_REQUEST_FORMAT;
import static org.almrangers.auth.aad.AadSettings.LOGIN_STRATEGY_PROVIDER_ID;
import static org.almrangers.auth.aad.AadSettings.LOGIN_STRATEGY_UNIQUE;
import static org.almrangers.auth.aad.AadSettings.SECURE_RESOURCE_URL;

@ServerSide
public class AadIdentityProvider implements OAuth2IdentityProvider {
Expand Down Expand Up @@ -122,7 +120,7 @@ public void callback(CallbackContext context) {
URI url = new URI(context.getCallbackUrl());
ClientCredential clientCredt = new ClientCredential(settings.clientId(), settings.clientSecret());
Future<AuthenticationResult> future = authContext.acquireTokenByAuthorizationCode(
oAuthVerifier, url, clientCredt, SECURE_RESOURCE_URL, null);
oAuthVerifier, url, clientCredt, settings.getGraphURL(), null);
result = future.get();

UserInfo aadUser = result.getUserInfo();
Expand Down Expand Up @@ -158,7 +156,7 @@ private String getLogin(UserInfo aadUser) {
}

URL getUrl(String userId, String nextPage) throws MalformedURLException {
String url = String.format(GROUPS_REQUEST_FORMAT, settings.tenantId(), userId);
String url = String.format(settings.getGraphMembershipUrl(), settings.tenantId(), userId);
// Append odata query parameters for subsequent pages
if (null != nextPage) {
url += "&" + nextPage;
Expand All @@ -173,9 +171,8 @@ public Set<String> getUserGroupsMembership(String accessToken, String userId) {
do {
URL url = getUrl(userId, nextPage);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("api-version", "1.6");
connection.setRequestProperty("Authorization", accessToken);
connection.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
connection.setRequestProperty("Accept", "application/json;odata.metadata=minimal");
String goodRespStr = HttpClientHelper.getResponseStringFromConn(connection, true);
int responseCode = connection.getResponseCode();
JSONObject response = HttpClientHelper.processGoodRespStr(responseCode, goodRespStr);
Expand Down
75 changes: 69 additions & 6 deletions src/main/java/org/almrangers/auth/aad/AadSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public class AadSettings {
protected static final String ENABLED = "sonar.auth.aad.enabled";
protected static final String ALLOW_USERS_TO_SIGN_UP = "sonar.auth.aad.allowUsersToSignUp";
protected static final String TENANT_ID = "sonar.auth.aad.tenantId";
protected static final String DIRECTORY_LOCATION = "sonar.auth.aad.directoryLocation";
protected static final String DIRECTORY_LOC_GLOBAL = "Azure AD (Global)";
protected static final String DIRECTORY_LOC_USGOV = "Azure AD for US Government";
protected static final String DIRECTORY_LOC_DE = "Azure AD for Germany";
protected static final String DIRECTORY_LOC_CN = "Azure AD China";
protected static final String ENABLE_GROUPS_SYNC = "sonar.auth.aad.enableGroupsSync";
protected static final String LOGIN_STRATEGY = "sonar.auth.aad.loginStrategy";
protected static final String LOGIN_STRATEGY_UNIQUE = "Unique";
Expand All @@ -55,14 +60,20 @@ public class AadSettings {
protected static final String SUBCATEGORY = "Authentication";
protected static final String GROUPSYNCSUBCATEGORY = "Groups Synchronization";

protected static final String ROOT_URL = "https://login.microsoftonline.com";
protected static final String LOGIN_URL = "https://login.microsoftonline.com";
protected static final String LOGIN_URL_USGOV = "https://login.microsoftonline.us";
protected static final String LOGIN_URL_DE = "https://login.microsoftonline.de";
protected static final String LOGIN_URL_CN = "https://login.chinacloudapi.cn";
protected static final String AUTHORIZATION_URL = "oauth2/authorize";
protected static final String AUTHORITY_URL = "oauth2/token";
protected static final String COMMON_URL = "common";
protected static final String SECURE_RESOURCE_URL = "https://graph.windows.net";

protected static final String GRAPH_URL = "https://graph.microsoft.com";
protected static final String GRAPH_URL_USGOV = "https://graph.microsoft.com";
protected static final String GRAPH_URL_DE = "https://graph.microsoft.de";
protected static final String GRAPH_URL_CN = "https://microsoftgraph.chinacloudapi.cn";
protected static final String AUTH_REQUEST_FORMAT = "%s?client_id=%s&response_type=code&redirect_uri=%s&state=%s&scope=openid";
protected static final String GROUPS_REQUEST_FORMAT = "https://graph.windows.net/%s/users/%s/memberOf?api-version=1.6";
protected static final String GROUPS_REQUEST_FORMAT = "/v1.0/%s/users/%s/memberOf";

private final Settings settings;

Expand Down Expand Up @@ -132,14 +143,24 @@ public static List<PropertyDefinition> definitions() {
.options(LOGIN_STRATEGY_UNIQUE, LOGIN_STRATEGY_PROVIDER_ID)
.index(7)
.build(),
PropertyDefinition.builder(DIRECTORY_LOCATION)
.name("Directory Location")
.description("The location of the Azure installation. You normally won't need to change this.")
.category(CATEGORY)
.subCategory(SUBCATEGORY)
.type(SINGLE_SELECT_LIST)
.defaultValue(DIRECTORY_LOC_GLOBAL)
.options(DIRECTORY_LOC_GLOBAL, DIRECTORY_LOC_USGOV, DIRECTORY_LOC_DE, DIRECTORY_LOC_CN)
.index(8)
.build(),
PropertyDefinition.builder(ENABLE_GROUPS_SYNC)
.name("Enable Groups Synchronization")
.description("Enable groups synchronization from Azure AD to SonarQube, For each Azure AD group user belongs to, the user will be associated to a group with the same name(if it exists) in SonarQube.")
.category(CATEGORY)
.subCategory(GROUPSYNCSUBCATEGORY)
.type(BOOLEAN)
.defaultValue(valueOf(false))
.index(8)
.index(9)
.build()

);
Expand Down Expand Up @@ -181,12 +202,54 @@ private String getEndpoint() {
}
}

private String getLoginHost() {
String directoryLocation = settings.getString(DIRECTORY_LOCATION);

switch (directoryLocation) {
case DIRECTORY_LOC_USGOV:
return LOGIN_URL_USGOV;

case DIRECTORY_LOC_DE:
return LOGIN_URL_DE;

case DIRECTORY_LOC_CN:
return LOGIN_URL_CN;

case DIRECTORY_LOC_GLOBAL:
default:
return LOGIN_URL;
}
}

public String authorizationUrl() {
return String.format("%s/%s/%s", ROOT_URL, getEndpoint(), AUTHORIZATION_URL);
return String.format("%s/%s/%s", getLoginHost(), getEndpoint(), AUTHORIZATION_URL);
}

public String authorityUrl() {
return String.format("%s/%s/%s", ROOT_URL, getEndpoint(), AUTHORITY_URL);
return String.format("%s/%s/%s", getLoginHost(), getEndpoint(), AUTHORITY_URL);
}

public String getGraphURL() {
String directoryLocation = settings.getString(DIRECTORY_LOCATION);

switch (directoryLocation) {
case DIRECTORY_LOC_USGOV:
return GRAPH_URL_USGOV;

case DIRECTORY_LOC_DE:
return GRAPH_URL_DE;

case DIRECTORY_LOC_CN:
return GRAPH_URL_CN;

case DIRECTORY_LOC_GLOBAL:
default:
return GRAPH_URL;
}
}

public String getGraphMembershipUrl() {
return getGraphURL() + GROUPS_REQUEST_FORMAT;
}

public String loginStrategy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ private void setSettings(boolean enabled) {
settings.setProperty("sonar.auth.aad.clientId.secured", "id");
settings.setProperty("sonar.auth.aad.clientSecret.secured", "secret");
settings.setProperty("sonar.auth.aad.loginStrategy", AadSettings.LOGIN_STRATEGY_DEFAULT_VALUE);
settings.setProperty("sonar.auth.aad.directoryLocation", AadSettings.DIRECTORY_LOC_GLOBAL);
settings.setProperty("sonar.auth.aad.enabled", true);
} else {
settings.setProperty("sonar.auth.aad.enabled", false);
Expand Down
27 changes: 25 additions & 2 deletions src/test/java/org/almrangers/auth/aad/AadSettingsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import org.sonar.api.config.Settings;
import org.sonar.api.config.internal.MapSettings;

import static org.almrangers.auth.aad.AadSettings.LOGIN_STRATEGY_DEFAULT_VALUE;
import static org.almrangers.auth.aad.AadSettings.*;
import static org.assertj.core.api.Assertions.assertThat;

public class AadSettingsTest {
Expand Down Expand Up @@ -65,6 +65,29 @@ public void return_authorization_url_for_multi_tenant_azureAd_app() {
assertThat(underTest.authorizationUrl()).isEqualTo("https://login.microsoftonline.com/common/oauth2/authorize");
}

@Test
public void return_correct_urls() {
//Azure Default "Global"
settings.setProperty("sonar.auth.aad.directoryLocation", DIRECTORY_LOC_GLOBAL);
assertThat(underTest.authorizationUrl().startsWith("https://login.microsoftonline.com"));
assertThat(underTest.getGraphURL().startsWith("https://graph.microsoft.com"));

//Azure US Gov
settings.setProperty("sonar.auth.aad.directoryLocation", DIRECTORY_LOC_USGOV);
assertThat(underTest.authorizationUrl().startsWith("https://login.microsoftonline.us"));
assertThat(underTest.getGraphURL().startsWith("https://graph.microsoft.com"));

//Azure Germany
settings.setProperty("sonar.auth.aad.directoryLocation", DIRECTORY_LOC_DE);
assertThat(underTest.authorizationUrl().startsWith("https://login.microsoftonline.de"));
assertThat(underTest.getGraphURL().startsWith("https://graph.microsoft.de"));

//Azure China
settings.setProperty("sonar.auth.aad.directoryLocation", DIRECTORY_LOC_CN);
assertThat(underTest.authorizationUrl().startsWith("https://login.chinacloudapi.cn"));
assertThat(underTest.getGraphURL().startsWith("https://microsoftgraph.chinacloudapi.cn"));
}

@Test
public void is_enabled_always_return_false_when_client_id_is_null() {
settings.setProperty("sonar.auth.aad.enabled", true);
Expand Down Expand Up @@ -113,7 +136,7 @@ public void allow_users_to_sign_up() {

@Test
public void definitions() {
assertThat(AadSettings.definitions()).hasSize(8);
assertThat(AadSettings.definitions()).hasSize(9);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class AuthAadPluginTest {

@Test
public void test_extensions() {
assertThat(underTest.getExtensions()).hasSize(10);
assertThat(underTest.getExtensions()).hasSize(11);
}

}