Skip to content

Commit

Permalink
The following were applied:
Browse files Browse the repository at this point in the history
 - Identity-specific is updated after succesfull registration. Refers #390, #355.
 - Minor fixes in the registration form (AdminUI). Refers #387.
 - Commented various KeycloakAdminClient methods. Still need cleaning up there.
  • Loading branch information
otsakir committed Aug 19, 2015
1 parent 7133f79 commit 21216ab
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.joda.time.DateTime;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.representations.idm.UserRepresentation;
import org.mobicents.servlet.restcomm.entities.Account;
import org.mobicents.servlet.restcomm.entities.AccountList;
Expand Down Expand Up @@ -164,7 +163,9 @@ private Account createFromUserRepresentation(final UserRepresentation userInfo)
}

protected Response importKeycloakAccount() {
logger.info("in importKeycloakAccount");
logger.warn("importKeycloakAccount(): this method is deprecated");
return status(INTERNAL_SERVER_ERROR).build();
/*
KeycloakSecurityContext session = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
if (session.getToken() != null) {
String loggedUsername = session.getToken().getPreferredUsername();
Expand Down Expand Up @@ -195,6 +196,7 @@ protected Response importKeycloakAccount() {
}
} else
return status(UNAUTHORIZED).build();
*/
}

protected Response getAccount(final String accountSid, final MediaType responseType) {
Expand Down Expand Up @@ -411,13 +413,18 @@ protected Response updateAccount(final String accountSid, final MultivaluedMap<S

private void updateKeycloakUser(Account restcommAccount) throws IOException, KeycloakClientException {
// retrieve the user from keycloak server, update and store back again
logger.warn("updateKeycloakUser(): this method is deprecated");
/*
UserRepresentation keycloakUser = keycloakClient.getUserInfo(restcommAccount.getEmailAddress());
keycloakUser.setFirstName(restcommAccount.getFriendlyName());
keycloakUser.setEnabled( (restcommAccount.getStatus() == Account.Status.ACTIVE) ) ;
keycloakClient.updateUser(restcommAccount.getEmailAddress(), keycloakUser);
*/
}

private void createKeycloakUser(Account restcommAccount, String password) throws KeycloakClientException {
logger.warn("updateKeycloakUser(): this method is deprecated");
/*
// create and populate keycloak user object
UserRepresentation user = new UserRepresentation();
user.setUsername(restcommAccount.getEmailAddress());
Expand All @@ -431,6 +438,7 @@ private void createKeycloakUser(Account restcommAccount, String password) throws
roles.add("RestcommUser");
roles.add("Developer");
keycloakClient.setUserRoles(restcommAccount.getEmailAddress(), roles);
*/
}

private void validate(final MultivaluedMap<String, String> data) throws NullPointerException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,36 @@

import java.util.UUID;

import javax.annotation.PostConstruct;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

import org.apache.commons.lang.StringUtils;
import org.mobicents.servlet.restcomm.identity.KeycloakClient;
import org.mobicents.servlet.restcomm.identity.KeycloakConfigurator;
import org.mobicents.servlet.restcomm.identity.KeycloakClient.KeycloakClientException;
import org.mobicents.servlet.restcomm.identity.KeycloakConfigurator.IdentityMode;

@Path("/instance")
public class IdentityEndpoint extends AbstractEndpoint {

public static String IDENTITY_PROXY_URL = "https://identity.restcomm.com/instance-manager";
//public static String IDENTITY_PROXY_URL = "https://identity.restcomm.com/instance-manager";
private KeycloakConfigurator keycloakConfigurator;



public IdentityEndpoint() {
// TODO Auto-generated constructor stub
}

@PostConstruct
private void init() {
keycloakConfigurator = (KeycloakConfigurator) context.getAttribute(KeycloakConfigurator.class.getName());
}


@POST
@Path("/register")
public Response registerInstance(@FormParam("restcommBaseUrl") String baseUrl, @FormParam("authUrl") String authUrl, @FormParam("username") String username, @FormParam("password") String password, @FormParam("instanceSecret") String instanceSecret ) throws KeycloakClientException {
Expand All @@ -32,9 +44,16 @@ public Response registerInstance(@FormParam("restcommBaseUrl") String baseUrl, @
keycloakClient.addParam("name", instanceName); // what we put here??
keycloakClient.addParam("prefix", baseUrl);
keycloakClient.addParam("secret", instanceSecret);
keycloakClient.makePostRequest(IDENTITY_PROXY_URL + "/api/instances"); // we assume that the identity proxy lives with the authorization server
keycloakClient.makePostRequest(keycloakConfigurator.getIdentityProxyUrl() + "/api/instances"); // we assume that the identity proxy lives together with the authorization server

// We're now registered. Update configuration. For now we will just store to RAM until a way is found to update restcomm.xml on the fly.
keycloakConfigurator.setAuthServerUrlBase(authUrl);
keycloakConfigurator.setMode(IdentityMode.cloud);
keycloakConfigurator.setRestcommClientSecret(instanceSecret);
keycloakConfigurator.setCloudInstanceId(instanceName);
keycloakConfigurator.updateRestcommXml(); // not effective until i find a way update restcomm.xml or store to database

logger.info( "User '" + username + "' registed this instance as '" + instanceName + "' at authorization server " + authUrl);
logger.info( "User '" + username + "' registed this instance as '" + instanceName + "' to authorization server " + authUrl);
return Response.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@
import org.keycloak.representations.AccessToken;
import org.mobicents.servlet.restcomm.entities.Account;
import org.mobicents.servlet.restcomm.entities.shiro.ShiroResources;
import org.mobicents.servlet.restcomm.identity.KeycloakAdminClient;

/**
*
* @author orestis.tsakiridis@telestax.com
*
*/
public abstract class SecuredEndpoint extends AbstractEndpoint {
protected KeycloakAdminClient keycloakClient;
//protected KeycloakAdminClient keycloakClient;
protected static RestcommRoles restcommRoles;

public SecuredEndpoint() {
Expand All @@ -32,7 +31,7 @@ protected void init(final Configuration configuration) {
super.init(configuration);
ShiroResources shiroResources = ShiroResources.getInstance();
restcommRoles = shiroResources.get(RestcommRoles.class);
keycloakClient = new KeycloakAdminClient();
//keycloakClient = new KeycloakAdminClient();
}

// Throws an authorization exception in case the user does not have the permission OR does not own (or is a parent) the account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
* @author "Tsakiridis Orestis"
*
*/
public class KeycloakConfigurator {
protected Logger logger = Logger.getLogger(KeycloakConfigurator.class);
public class IdentityConfigurator {
protected Logger logger = Logger.getLogger(IdentityConfigurator.class);

public static class CloudIdentityNotSet extends Exception {}

private static KeycloakConfigurator singleInstance;
private static IdentityConfigurator singleInstance;

public enum IdentityMode {
init,
Expand All @@ -36,31 +36,32 @@ public enum IdentityMode {
// Fixed values for known properties that will help testing.They will be overriden in the long run.
private final String realmKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB";
private final String realmName = "restcomm";
private final String authServerUrl = "https://identity.restcomm.com/auth";
private final String cloudInstanceId; // instance ID on identity.restcomm.com
private final String restcommClientSecret;
//private String authServerUrl = "https://identity.restcomm.com/auth";
private String authServerUrlBase = "https://identity.restcomm.com";
private String cloudInstanceId; // instance ID on identity.restcomm.com
private String restcommClientSecret;
private final String contextPath;
private final String identityModeInConfig;
private final IdentityMode identityMode;
private IdentityMode identityMode;

public static KeycloakConfigurator create(Configuration restcommConfiguration, ServletContext context) {
public static IdentityConfigurator create(Configuration restcommConfiguration, ServletContext context) {
// TODO - throw an exception if the instance has already been created??
if (singleInstance != null) {
throw new IllegalStateException("Singleton KeycloakConfigurator instance has already been created.");
}

singleInstance = new KeycloakConfigurator(restcommConfiguration, context);
singleInstance = new IdentityConfigurator(restcommConfiguration, context);
return singleInstance;
}

public static KeycloakConfigurator getInstance() {
public static IdentityConfigurator getInstance() {
if ( singleInstance == null )
throw new IllegalStateException("KeycloakConfigurator singleton has not been created yet. Make sure restcomm bootstrapper has run.");

return singleInstance;
}

private KeycloakConfigurator(Configuration restcommConfiguration, ServletContext context) {
private IdentityConfigurator(Configuration restcommConfiguration, ServletContext context) {
this.identityModeInConfig = restcommConfiguration.getString("runtime-settings.identity.mode");
this.cloudInstanceId = restcommConfiguration.getString("runtime-settings.identity.instance-id");
this.restcommClientSecret = restcommConfiguration.getString("runtime-settings.identity.restcomm-client-secret");
Expand All @@ -78,17 +79,35 @@ public String getRealmName() {
}

public String getAuthServerUrl() {
return authServerUrl;
return authServerUrlBase + "/auth";
}

public String getIdentityProxyUrl() {
return authServerUrlBase + "/instance-manager";
}

public void setAuthServerUrlBase(String authServerUrlBase) {
this.authServerUrlBase = authServerUrlBase;
}

public String getCloudInstanceId() {
return cloudInstanceId;
}

public void setCloudInstanceId(String identityInstanceId) {
this.cloudInstanceId = identityInstanceId;
}

public String getContextPath() {
return contextPath;
}

public void setRestcommClientSecret(String restcommClientSecret) {
this.restcommClientSecret = restcommClientSecret;
}



/**
* Implements logic for determining identity mode based on config.
* By default 'init' is used. If mode is missing from conf and instance-id is defined return 'cloud'. Return 'standalone' only if explicitly set to that value.
Expand Down Expand Up @@ -117,6 +136,10 @@ public IdentityMode getMode() {
return identityMode;
}

public void setMode(IdentityMode mode) {
this.identityMode = mode;
}

public boolean isHookedUpToKeycloak() {
return ! StringUtils.isEmpty(cloudInstanceId);
}
Expand Down Expand Up @@ -171,6 +194,11 @@ public BaseAdapterConfig getRestcommRvdUIConfig() throws CloudIdentityNotSet {
return config;
}

// update central configuration file restcomm.xml with current identity options.
public void updateRestcommXml() {
logger.warn("restcomm.xml has not been updated on the fly. You will need to stop, update manually and start your server. Here are the details: mode = " + getMode().toString() + ", instance-id = " + cloudInstanceId + ", restcomm-client-secret = " + restcommClientSecret + ", auth-server-url-base = " + authServerUrlBase );
}

// not used
public void persistRestcommConfig() throws IOException, CloudIdentityNotSet {
String path = contextPath + "/WEB-INF/keycloak.json";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.mobicents.servlet.restcomm.identity.KeycloakConfigurator.CloudIdentityNotSet;
import org.mobicents.servlet.restcomm.identity.IdentityConfigurator.CloudIdentityNotSet;

public class RestcommConfKeycloakResolver implements KeycloakConfigResolver {

Expand All @@ -18,7 +18,7 @@ public RestcommConfKeycloakResolver() {
@Override
public KeycloakDeployment resolve(Request request) {
if ( cache == null) {
KeycloakConfigurator configurator = KeycloakConfigurator.getInstance();
IdentityConfigurator configurator = IdentityConfigurator.getInstance();
try {
cache = KeycloakDeploymentBuilder.build(configurator.getRestcommConfig());
} catch (CloudIdentityNotSet e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.mobicents.servlet.restcomm.identity.entities;

import org.mobicents.servlet.restcomm.identity.KeycloakConfigurator.IdentityMode;
import org.mobicents.servlet.restcomm.identity.IdentityConfigurator.IdentityMode;

public class IdentityModeEntity {
private IdentityMode mode;
Expand Down
4 changes: 2 additions & 2 deletions restcomm/restcomm.ui/src/main/webapp/keycloak-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ angular.element(document).ready(function ($http) {
angular.module("rcApp").constant("authMode",data.mode);
if (data.mode == "cloud") {

var keycloakAuth = new Keycloak('/restcomm/keycloak/config/restcomm-ui.json');
var keycloakAuth = new Keycloak('/restcomm/identity/config/restcomm-ui.json');
auth.loggedIn = false;

keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
auth.loggedIn = true;
auth.authz = keycloakAuth;
auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/restcomm/tokens/logout?redirect_uri=" + window.location.origin + "/restcomm-management/index.html";
auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/restcomm/tokens/logout?redirect_uri=" + window.location.origin + "/index.html";
angular.module('rcApp').factory('Auth', function() {
return auth;
});
Expand Down
2 changes: 1 addition & 1 deletion restcomm/restcomm.ui/src/main/webapp/modules/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<label class="control-label">Authorization server</label>
</div>
<div class="col-md-6">
<p class="form-control-static text-muted">{{instance.authServer}}</p>
<p class="form-control-static text-muted">{{instance.authUrl}}</p>
</div>
</div>

Expand Down

0 comments on commit 21216ab

Please sign in to comment.