Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
2 changes: 2 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -1322,8 +1322,10 @@ public class ApiConstants {
public static final String VNF_CONFIGURE_MANAGEMENT = "vnfconfiguremanagement";
public static final String VNF_CIDR_LIST = "vnfcidrlist";

public static final String AUTHORIZE_URL = "authorizeurl";
public static final String CLIENT_ID = "clientid";
public static final String REDIRECT_URI = "redirecturi";
public static final String TOKEN_URL = "tokenurl";

public static final String IS_TAG_A_RULE = "istagarule";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,7 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tin

--- Disable/enable NICs
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nics','enabled', 'TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''Indicates whether the NIC is enabled or not'' ');

--- Add URLs for OAuth provider
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.oauth_provider','authorize_url', 'VARCHAR(255) DEFAULT NULL COMMENT ''Authorize URL for OAuth initialization'' ');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.oauth_provider','token_url', 'VARCHAR(255) DEFAULT NULL COMMENT ''Token URL for OAuth finalization'' ');
5 changes: 5 additions & 0 deletions plugins/user-authenticators/oauth2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
<artifactId>cloud-framework-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-security-jose</artifactId>
<version>${cs.cxf.version}</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-docs</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
//
package org.apache.cloudstack.oauth2;

import com.cloud.user.dao.UserDao;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.apache.cloudstack.auth.UserOAuth2Authenticator;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
Expand All @@ -35,16 +39,11 @@
import org.apache.cloudstack.oauth2.vo.OauthProviderVO;
import org.apache.commons.lang3.StringUtils;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;

public class OAuth2AuthManagerImpl extends ManagerBase implements OAuth2AuthManager, Manager, Configurable {
@Inject
private UserDao _userDao;

@Inject
protected OauthProviderDao _oauthProviderDao;
Expand All @@ -55,7 +54,7 @@ public class OAuth2AuthManagerImpl extends ManagerBase implements OAuth2AuthMana

@Override
public List<Class<?>> getAuthCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();
List<Class<?>> cmdList = new ArrayList<>();
cmdList.add(OauthLoginAPIAuthenticatorCmd.class);
cmdList.add(ListOAuthProvidersCmd.class);
cmdList.add(VerifyOAuthCodeAndGetUserCmd.class);
Expand Down Expand Up @@ -84,7 +83,7 @@ public boolean stop() {

@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();
List<Class<?>> cmdList = new ArrayList<>();
cmdList.add(RegisterOAuthProviderCmd.class);
cmdList.add(DeleteOAuthProviderCmd.class);
cmdList.add(UpdateOAuthProviderCmd.class);
Expand Down Expand Up @@ -127,9 +126,7 @@ protected void initializeUserOAuth2AuthenticationProvidersMap() {
@Override
public String verifyCodeAndFetchEmail(String code, String provider) {
UserOAuth2Authenticator authenticator = getUserOAuth2AuthenticationProvider(provider);
String email = authenticator.verifyCodeAndFetchEmail(code);

return email;
return authenticator.verifyCodeAndFetchEmail(code);
}

@Override
Expand All @@ -139,6 +136,8 @@ public OauthProviderVO registerOauthProvider(RegisterOAuthProviderCmd cmd) {
String clientId = StringUtils.trim(cmd.getClientId());
String redirectUri = StringUtils.trim(cmd.getRedirectUri());
String secretKey = StringUtils.trim(cmd.getSecretKey());
String authorizeUrl = StringUtils.trim(cmd.getAuthorizeUrl());
String tokenUrl = StringUtils.trim(cmd.getTokenUrl());

if (!isOAuthPluginEnabled()) {
throw new CloudRuntimeException("OAuth is not enabled, please enable to register");
Expand All @@ -148,7 +147,7 @@ public OauthProviderVO registerOauthProvider(RegisterOAuthProviderCmd cmd) {
throw new CloudRuntimeException(String.format("Provider with the name %s is already registered", provider));
}

return saveOauthProvider(provider, description, clientId, secretKey, redirectUri);
return saveOauthProvider(provider, description, clientId, secretKey, redirectUri, authorizeUrl, tokenUrl);
}

@Override
Expand All @@ -171,6 +170,8 @@ public OauthProviderVO updateOauthProvider(UpdateOAuthProviderCmd cmd) {
String clientId = StringUtils.trim(cmd.getClientId());
String redirectUri = StringUtils.trim(cmd.getRedirectUri());
String secretKey = StringUtils.trim(cmd.getSecretKey());
String authorizeUrl = StringUtils.trim(cmd.getAuthorizeUrl());
String tokenUrl = StringUtils.trim(cmd.getTokenUrl());
Boolean enabled = cmd.getEnabled();

OauthProviderVO providerVO = _oauthProviderDao.findById(id);
Expand All @@ -190,6 +191,12 @@ public OauthProviderVO updateOauthProvider(UpdateOAuthProviderCmd cmd) {
if (StringUtils.isNotEmpty(secretKey)) {
providerVO.setSecretKey(secretKey);
}
if (StringUtils.isNotEmpty(authorizeUrl)) {
providerVO.setAuthorizeUrl(authorizeUrl);
}
if (StringUtils.isNotEmpty(tokenUrl)) {
providerVO.setTokenUrl(tokenUrl);
}
if (enabled != null) {
providerVO.setEnabled(enabled);
}
Expand All @@ -199,14 +206,16 @@ public OauthProviderVO updateOauthProvider(UpdateOAuthProviderCmd cmd) {
return _oauthProviderDao.findById(id);
}

private OauthProviderVO saveOauthProvider(String provider, String description, String clientId, String secretKey, String redirectUri) {
private OauthProviderVO saveOauthProvider(String provider, String description, String clientId, String secretKey, String redirectUri, String authorizeUrl, String tokenUrl) {
final OauthProviderVO oauthProviderVO = new OauthProviderVO();

oauthProviderVO.setProvider(provider);
oauthProviderVO.setDescription(description);
oauthProviderVO.setClientId(clientId);
oauthProviderVO.setSecretKey(secretKey);
oauthProviderVO.setRedirectUri(redirectUri);
oauthProviderVO.setAuthorizeUrl(authorizeUrl);
oauthProviderVO.setTokenUrl(tokenUrl);
oauthProviderVO.setEnabled(true);

_oauthProviderDao.persist(oauthProviderVO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
import java.util.List;
import java.util.Map;

import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.user.Account;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
Expand All @@ -40,9 +42,8 @@
import org.apache.cloudstack.oauth2.vo.OauthProviderVO;
import org.apache.commons.lang.ArrayUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.user.Account;

@APICommand(name = "listOauthProvider", description = "List OAuth providers registered", responseObject = OauthProviderResponse.class, entityType = {},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
Expand Down Expand Up @@ -108,7 +109,7 @@ public String authenticate(String command, Map<String, Object[]> params, HttpSes
List<OauthProviderResponse> responses = new ArrayList<>();
for (OauthProviderVO result : resultList) {
OauthProviderResponse r = new OauthProviderResponse(result.getUuid(), result.getProvider(),
result.getDescription(), result.getClientId(), result.getSecretKey(), result.getRedirectUri());
result.getDescription(), result.getClientId(), result.getSecretKey(), result.getRedirectUri(), result.getAuthorizeUrl(), result.getTokenUrl());
if (OAuth2AuthManager.OAuth2IsPluginEnabled.value() && authenticatorPluginNames.contains(result.getProvider()) && result.isEnabled()) {
r.setEnabled(true);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,28 @@
// limitations under the License.
package org.apache.cloudstack.oauth2.api.command;

import java.util.Collection;
import java.util.Map;

import javax.inject.Inject;
import javax.persistence.EntityExistsException;

import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.oauth2.OAuth2AuthManager;
import org.apache.cloudstack.oauth2.api.response.OauthProviderResponse;
import org.apache.cloudstack.oauth2.vo.OauthProviderVO;
import org.apache.commons.collections.MapUtils;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.oauth2.OAuth2AuthManager;
import org.apache.cloudstack.oauth2.api.response.OauthProviderResponse;
import org.apache.cloudstack.oauth2.vo.OauthProviderVO;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.collections.MapUtils;

import com.cloud.exception.ConcurrentOperationException;

import java.util.Collection;
import java.util.Map;

@APICommand(name = "registerOauthProvider", responseObject = SuccessResponse.class, description = "Register the OAuth2 provider in CloudStack", since = "4.19.0")
public class RegisterOAuthProviderCmd extends BaseCmd {

Expand All @@ -56,6 +58,12 @@ public class RegisterOAuthProviderCmd extends BaseCmd {
@Parameter(name = ApiConstants.REDIRECT_URI, type = CommandType.STRING, description = "Redirect URI pre-registered in the specific OAuth provider", required = true)
private String redirectUri;

@Parameter(name = ApiConstants.AUTHORIZE_URL, type = CommandType.STRING, description = "Authorize URL for OAuth initialization (only required for keyloack provider)")
Comment thread
DaanHoogland marked this conversation as resolved.
Outdated
private String authorizeUrl;

@Parameter(name = ApiConstants.TOKEN_URL, type = CommandType.STRING, description = "Token URL for OAuth finalization (only required for keycloak provider)")
private String tokenUrl;

@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP,
description = "Any OAuth provider details in key/value pairs using format details[i].keyname=keyvalue. Example: details[0].clientsecret=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")
protected Map details;
Expand Down Expand Up @@ -85,6 +93,14 @@ public String getRedirectUri() {
return redirectUri;
}

public String getAuthorizeUrl() {
return authorizeUrl;
}

public String getTokenUrl() {
return tokenUrl;
}

public Map getDetails() {
if (MapUtils.isEmpty(details)) {
return null;
Expand All @@ -98,10 +114,20 @@ public Map getDetails() {

@Override
public void execute() throws ServerApiException, ConcurrentOperationException, EntityExistsException {
if (StringUtils.equals("keycloak", getProvider())) {
Comment thread
tazouxme marked this conversation as resolved.
Outdated
if (getAuthorizeUrl() == null || "".equals(getAuthorizeUrl())) {
throw new ServerApiException(ApiErrorCode.BAD_REQUEST, "Parameter authorizationurl is mandatory for keycloak OAuth Provider");
Comment thread
DaanHoogland marked this conversation as resolved.
Outdated
Comment thread
DaanHoogland marked this conversation as resolved.
Outdated
}
if (getTokenUrl() == null || "".equals(getTokenUrl())) {
throw new ServerApiException(ApiErrorCode.BAD_REQUEST, "Parameter tokenurl is mandatory for keycloak OAuth Provider");
}
}

OauthProviderVO provider = _oauth2mgr.registerOauthProvider(this);

OauthProviderResponse response = new OauthProviderResponse(provider.getUuid(), provider.getProvider(),
provider.getDescription(), provider.getClientId(), provider.getSecretKey(), provider.getRedirectUri());
provider.getDescription(), provider.getClientId(), provider.getSecretKey(), provider.getRedirectUri(),
provider.getAuthorizeUrl(), provider.getTokenUrl());
response.setResponseName(getCommandName());
response.setObjectName(ApiConstants.OAUTH_PROVIDER);
setResponseObject(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@
// under the License.
package org.apache.cloudstack.oauth2.api.command;

import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.auth.UserOAuth2Authenticator;
import org.apache.cloudstack.oauth2.OAuth2AuthManager;
import org.apache.cloudstack.oauth2.api.response.OauthProviderResponse;
import org.apache.cloudstack.oauth2.vo.OauthProviderVO;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.auth.UserOAuth2Authenticator;
import org.apache.cloudstack.context.CallContext;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.oauth2.OAuth2AuthManager;
import org.apache.cloudstack.oauth2.api.response.OauthProviderResponse;
import org.apache.cloudstack.oauth2.vo.OauthProviderVO;

@APICommand(name = "updateOauthProvider", description = "Updates the registered OAuth provider details", responseObject = OauthProviderResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0")
Expand All @@ -57,6 +57,12 @@ public final class UpdateOAuthProviderCmd extends BaseCmd {
@Parameter(name = ApiConstants.REDIRECT_URI, type = CommandType.STRING, description = "Redirect URI pre-registered in the specific OAuth provider")
private String redirectUri;

@Parameter(name = ApiConstants.AUTHORIZE_URL, type = CommandType.STRING, description = "Authorize URL pre-registered in the specific OAuth provider")
private String authorizeUrl;

@Parameter(name = ApiConstants.TOKEN_URL, type = CommandType.STRING, description = "Token URL pre-registered in the specific OAuth provider")
private String tokenUrl;

@Parameter(name = ApiConstants.ENABLED, type = CommandType.BOOLEAN, description = "OAuth provider will be enabled or disabled based on this value")
private Boolean enabled;

Expand Down Expand Up @@ -87,6 +93,14 @@ public String getRedirectUri() {
return redirectUri;
}

public String getAuthorizeUrl() {
return authorizeUrl;
}

public String getTokenUrl() {
return tokenUrl;
}

public Boolean getEnabled() {
return enabled;
}
Expand Down Expand Up @@ -115,7 +129,8 @@ public void execute() {
OauthProviderVO result = _oauthMgr.updateOauthProvider(this);
if (result != null) {
OauthProviderResponse r = new OauthProviderResponse(result.getUuid(), result.getProvider(),
result.getDescription(), result.getClientId(), result.getSecretKey(), result.getRedirectUri());
result.getDescription(), result.getClientId(), result.getSecretKey(), result.getRedirectUri(),
result.getAuthorizeUrl(), result.getTokenUrl());

List<UserOAuth2Authenticator> userOAuth2AuthenticatorPlugins = _oauthMgr.listUserOAuth2AuthenticationProviders();
List<String> authenticatorPluginNames = new ArrayList<>();
Expand Down
Loading
Loading