diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/web.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/web.xml
index 11c9c5c6d0..8e5878d647 100644
--- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/web.xml
+++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/web.xml
@@ -64,7 +64,7 @@
restAPI
- /2012-04-24/Profiles/*
+ /2012-04-24/*
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsEndpoint.java
index 36c5df3e2b..6326c3f29a 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsEndpoint.java
@@ -179,7 +179,6 @@ public LinkHeader composeLink(Sid targetSid, UriInfo info) {
}
protected Response getAccount(final String accountSid, final MediaType responseType, UriInfo info) {
- checkAuthenticatedAccount();
//First check if the account has the required permissions in general, this way we can fail fast and avoid expensive DAO operations
Account account = null;
checkPermission("RestComm:Read:Accounts");
@@ -347,7 +346,6 @@ private void removeIncomingPhoneNumbers(Sid accountSid, IncomingPhoneNumbersDao
protected Response getAccounts(final UriInfo info, final MediaType responseType) {
- checkAuthenticatedAccount();
//First check if the account has the required permissions in general, this way we can fail fast and avoid expensive DAO operations
checkPermission("RestComm:Read:Accounts");
final Account account = userIdentityContext.getEffectiveAccount();
@@ -389,7 +387,6 @@ protected Response getAccounts(final UriInfo info, final MediaType responseType)
}
protected Response putAccount(final MultivaluedMap data, final MediaType responseType) {
- checkAuthenticatedAccount();
//First check if the account has the required permissions in general, this way we can fail fast and avoid expensive DAO operations
checkPermission("RestComm:Create:Accounts");
// check account level depth. If we're already at third level no sub-accounts are allowed to be created
@@ -561,7 +558,6 @@ private Account prepareAccountForUpdate(final Account account, final Multivalued
protected Response updateAccount(final String identifier, final MultivaluedMap data,
final MediaType responseType) {
- checkAuthenticatedAccount();
// First check if the account has the required permissions in general, this way we can fail fast and avoid expensive DAO
// operations
checkPermission("RestComm:Modify:Accounts");
@@ -666,11 +662,6 @@ private Organization getOrganization(final MultivaluedMap data)
protected Response migrateAccountOrganization(final String identifier, final MultivaluedMap data,
final MediaType responseType) {
- //Validation 1 - Only SuperAdmin is allowed to migrate organization for an Account
- if (!isSuperAdmin()) {
- throw new InsufficientPermission();
- }
-
Organization organization = getOrganization(data);
//Validation 2 - Check if data contains Organization (either SID or domain name)
if (organization == null) {
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsJsonEndpoint.java
index 04f9c00e05..e6eefe9592 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsJsonEndpoint.java
@@ -21,7 +21,9 @@
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS;
@@ -101,6 +103,7 @@ public Response updateAccountAsJsonPut(@PathParam("accountSid") final String acc
@Path("/migrate/{accountSid}")
@Consumes(APPLICATION_FORM_URLENCODED)
@POST
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response migrateAccount(@PathParam("accountSid") final String accountSid, final MultivaluedMap data) {
return migrateAccountOrganization(accountSid, data, APPLICATION_JSON_TYPE);
}
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsXmlEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsXmlEndpoint.java
index 3d8f97c387..46cf8c1f99 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsXmlEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsXmlEndpoint.java
@@ -34,6 +34,9 @@
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+
+import javax.annotation.security.RolesAllowed;
/**
* @author quintana.thomas@gmail.com (Thomas Quintana)
@@ -92,6 +95,7 @@ public Response updateAccountAsXmlPut(@PathParam("accountSid") final String acco
@Path("/migrate/{accountSid}")
@Consumes(APPLICATION_FORM_URLENCODED)
@POST
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response migrateAccount(@PathParam("accoutSid") final String accountSid, final MultivaluedMap data) {
return migrateAccountOrganization(accountSid, data, APPLICATION_XML_TYPE);
}
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java
index f2073ec698..a2e0d57648 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java
@@ -33,7 +33,6 @@
import org.restcomm.connect.extension.api.ExtensionConfiguration;
import org.restcomm.connect.http.converter.ExtensionConfigurationConverter;
import org.restcomm.connect.http.converter.RestCommResponseConverter;
-import org.restcomm.connect.http.exceptions.InsufficientPermission;
import javax.annotation.PostConstruct;
import javax.ws.rs.core.MediaType;
@@ -78,8 +77,6 @@ void init() {
xstream.registerConverter(converter);
xstream.registerConverter(new ExtensionConfigurationConverter(configuration));
xstream.registerConverter(new RestCommResponseConverter(configuration));
- // Make sure there is an authenticated account present when this endpoint is used
- checkAuthenticatedAccount();
}
/**
@@ -90,9 +87,6 @@ void init() {
*/
protected Response getConfiguration(final String extensionId, final Sid accountSid, final MediaType responseType) {
//Parameter "extensionId" could be the extension Sid or extension name.
- if (!isSuperAdmin()) {
- throw new InsufficientPermission();
- }
ExtensionConfiguration extensionConfiguration = null;
ExtensionConfiguration extensionAccountConfiguration = null;
@@ -173,9 +167,6 @@ private ExtensionConfiguration createFrom(final MultivaluedMap d
}
protected Response postConfiguration(final MultivaluedMap data, final MediaType responseType) {
- if (!isSuperAdmin()) {
- throw new InsufficientPermission();
- }
Sid accountSid = null;
@@ -221,9 +212,6 @@ protected Response postConfiguration(final MultivaluedMap data,
}
protected Response updateConfiguration(String extensionSid, MultivaluedMap data, MediaType responseType) {
- if (!isSuperAdmin()) {
- throw new InsufficientPermission();
- }
if (!Sid.pattern.matcher(extensionSid).matches()) {
return status(BAD_REQUEST).build();
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationJsonEndpoint.java
index f96534542f..5ceb4cf5a6 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationJsonEndpoint.java
@@ -30,11 +30,15 @@
import org.restcomm.connect.commons.dao.Sid;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+
+import javax.annotation.security.RolesAllowed;
/**
* Created by gvagenas on 12/10/2016.
*/
@Path("/ExtensionsConfiguration.json")
+@RolesAllowed(SUPER_ADMIN_ROLE)
public class ExtensionsConfigurationJsonEndpoint extends ExtensionsConfigurationEndpoint {
@Path("/{extensionId}")
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationXmlEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationXmlEndpoint.java
index f0ad07970f..ede1ea96a5 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationXmlEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationXmlEndpoint.java
@@ -34,8 +34,12 @@
import org.restcomm.connect.commons.dao.Sid;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+
+import javax.annotation.security.RolesAllowed;
@Path("/ExtensionsConfiguration")
+@RolesAllowed(SUPER_ADMIN_ROLE)
public class ExtensionsConfigurationXmlEndpoint extends ExtensionsConfigurationEndpoint {
@Path("/{extensionId}")
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysEndpoint.java
index 49e4748874..62b5d3e0f3 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysEndpoint.java
@@ -92,10 +92,6 @@ private Gateway createFrom(final MultivaluedMap data) {
}
protected Response getGateway(final String accountSid, final String sid, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Read:Gateways");
final Gateway gateway = dao.getGateway(new Sid(sid));
if (gateway == null) {
return status(NOT_FOUND).build();
@@ -112,10 +108,6 @@ protected Response getGateway(final String accountSid, final String sid, final M
}
protected Response getGateways(final String accountSid, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Read:Gateways");
final List gateways = dao.getGateways();
if (APPLICATION_XML_TYPE == responseType) {
final RestCommResponse response = new RestCommResponse(new GatewayList(gateways));
@@ -128,10 +120,7 @@ protected Response getGateways(final String accountSid, final MediaType response
}
protected Response putGateway(final String accountSid, final MultivaluedMap data, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Create:Gateways");
+
try {
validate(data);
} catch (final RuntimeException exception) {
@@ -154,10 +143,7 @@ protected Response putGateway(final String accountSid, final MultivaluedMap data, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Modify:Gateways");
+
Gateway gateway = dao.getGateway(new Sid(sid));
if (gateway == null) {
return status(NOT_FOUND).build();
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysJsonEndpoint.java
index c9e6bbd33a..e4bd79b2cd 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysJsonEndpoint.java
@@ -20,7 +20,9 @@
package org.restcomm.connect.http;
import static javax.ws.rs.core.MediaType.*;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -35,6 +37,7 @@
*/
@Path("/Accounts/{accountSid}/Management/Gateways.json")
@ThreadSafe
+@RolesAllowed(SUPER_ADMIN_ROLE)
public class GatewaysJsonEndpoint extends GatewaysEndpoint {
public GatewaysJsonEndpoint() {
super();
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysXmlEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysXmlEndpoint.java
index acd50e8cd6..e64acec386 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysXmlEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/GatewaysXmlEndpoint.java
@@ -21,7 +21,9 @@
import static javax.ws.rs.core.MediaType.*;
import static javax.ws.rs.core.Response.*;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -39,6 +41,7 @@
*/
@Path("/Accounts/{accountSid}/Management/Gateways")
@ThreadSafe
+@RolesAllowed(SUPER_ADMIN_ROLE)
public final class GatewaysXmlEndpoint extends GatewaysEndpoint {
public GatewaysXmlEndpoint() {
super();
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersEndpoint.java
index 063cc91e96..29d7701cfd 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersEndpoint.java
@@ -660,7 +660,6 @@ public static org.restcomm.connect.provisioning.number.api.PhoneNumber convertIn
protected Response migrateIncomingPhoneNumbers(String targetAccountSid, MultivaluedMap data, MediaType responseType) {
Account effectiveAccount = userIdentityContext.getEffectiveAccount();
secure(effectiveAccount, "RestComm:Modify:IncomingPhoneNumbers");
- allowOnlySuperAdmin();
try{
Account targetAccount = accountsDao.getAccount(targetAccountSid);
// this is to avoid if mistakenly provided super admin account as targetAccountSid
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersXmlEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersXmlEndpoint.java
index 728c9b457e..5ca96038b6 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersXmlEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/IncomingPhoneNumbersXmlEndpoint.java
@@ -21,7 +21,9 @@
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -212,6 +214,7 @@ public Response putIncomingMobilePhoneNumberAsJSon(@PathParam("accountSid") fina
@Path("/migrate")
@POST
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response migrateIncomingPhoneNumbersAsXml(@PathParam("accountSid") final String accountSid,
final MultivaluedMap data) {
return migrateIncomingPhoneNumbers(accountSid, data, APPLICATION_XML_TYPE);
@@ -219,6 +222,7 @@ public Response migrateIncomingPhoneNumbersAsXml(@PathParam("accountSid") final
@Path("/migrate.json")
@POST
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response migrateIncomingPhoneNumbersAsJson(@PathParam("accountSid") final String accountSid,
final MultivaluedMap data) {
return migrateIncomingPhoneNumbers(accountSid, data, APPLICATION_JSON_TYPE);
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsEndpoint.java
index bd1734fa94..2e54a2f252 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsEndpoint.java
@@ -141,7 +141,6 @@ public LinkHeader composeLink(Sid targetSid, UriInfo info) {
*/
protected Response getOrganization(final String organizationSid, final MediaType responseType,
UriInfo info) {
- checkAuthenticatedAccount();
//First check if the account has the required permissions in general, this way we can fail fast and avoid expensive DAO operations
checkPermission("RestComm:Read:Organizations");
Organization organization = null;
@@ -191,9 +190,6 @@ protected Response getOrganization(final String organizationSid, final MediaType
* @return
*/
protected Response getOrganizations(UriInfo info, final MediaType responseType) {
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-
List organizations = null;
String status = info.getQueryParameters().getFirst("Status");
@@ -228,8 +224,6 @@ protected Response putOrganization(String domainName, final UriInfo info,
if(domainName == null){
return status(BAD_REQUEST).entity(MSG_EMPTY_DOMAIN_NAME ).build();
}else{
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
//Character verification
if(!pattern.matcher(domainName).matches()){
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsJsonEndpoint.java
index 7691c4fc12..aab9e9aeaf 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsJsonEndpoint.java
@@ -20,7 +20,9 @@
package org.restcomm.connect.http;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
@@ -49,12 +51,14 @@ public Response getOrganizationAsJson(@PathParam("organizationSid") final String
}
@GET
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response getOrganizations(@Context UriInfo info) {
return getOrganizations(info, APPLICATION_JSON_TYPE);
}
@Path("/{domainName}")
@PUT
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response putOrganizationPut(@PathParam("domainName") final String domainName, @Context UriInfo info) {
return putOrganization(domainName, info, APPLICATION_JSON_TYPE);
}
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsXmlEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsXmlEndpoint.java
index f56a6853d1..4982eb04d3 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsXmlEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OrganizationsXmlEndpoint.java
@@ -20,7 +20,9 @@
package org.restcomm.connect.http;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
@@ -36,6 +38,7 @@
*/
@Path("/Organizations")
@ThreadSafe
+@RolesAllowed(SUPER_ADMIN_ROLE)
public final class OrganizationsXmlEndpoint extends OrganizationsEndpoint {
public OrganizationsXmlEndpoint() {
super();
@@ -49,12 +52,14 @@ public Response getOrganizationAsXml(@PathParam("organizationSid") final String
}
@GET
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response getOrganizations(@Context UriInfo info) {
return getOrganizations(info, APPLICATION_XML_TYPE);
}
@Path("/{domainName}")
@PUT
+ @RolesAllowed(SUPER_ADMIN_ROLE)
public Response putOrganizationPut(@PathParam("domainName") final String domainName, @Context UriInfo info) {
return putOrganization(domainName, info, APPLICATION_XML_TYPE);
}
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyEndpoint.java
index 94582b787e..3fb12dbbc7 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyEndpoint.java
@@ -89,10 +89,6 @@ public void init() {
}
protected Response getProxies(final String accountSid, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Read:OutboundProxies");
Map proxies;
@@ -115,10 +111,6 @@ protected Response getProxies(final String accountSid, final MediaType responseT
}
protected Response switchProxy(final String accountSid, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Read:OutboundProxies");
Map proxyAfterSwitch;
@@ -141,10 +133,6 @@ protected Response switchProxy(final String accountSid, final MediaType response
}
protected Response getActiveProxy(final String accountSid, final MediaType responseType) {
- //following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
-// secure(accountsDao.getAccount(accountSid), "RestComm:Read:OutboundProxies");
Map activeProxy;
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyJsonEndpoint.java
index be010a1937..36ec9961fc 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyJsonEndpoint.java
@@ -21,7 +21,9 @@
package org.restcomm.connect.http;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -35,6 +37,7 @@
*/
@Path("/Accounts/{accountSid}/OutboundProxy.json")
@ThreadSafe
+@RolesAllowed(SUPER_ADMIN_ROLE)
public class OutboundProxyJsonEndpoint extends OutboundProxyEndpoint {
public OutboundProxyJsonEndpoint() {
super();
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyXmlEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyXmlEndpoint.java
index 6359745454..4a4930abf1 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyXmlEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/OutboundProxyXmlEndpoint.java
@@ -21,7 +21,9 @@
package org.restcomm.connect.http;
import static javax.ws.rs.core.MediaType.*;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -35,6 +37,7 @@
*/
@Path("/Accounts/{accountSid}/OutboundProxy")
@ThreadSafe
+@RolesAllowed(SUPER_ADMIN_ROLE)
public class OutboundProxyXmlEndpoint extends OutboundProxyEndpoint {
public OutboundProxyXmlEndpoint() {
super();
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ProfileJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ProfileJsonEndpoint.java
index 091fa6a9f9..99f6d4769c 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ProfileJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ProfileJsonEndpoint.java
@@ -38,15 +38,13 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.restcomm.connect.commons.annotations.concurrency.ThreadSafe;
-import static org.restcomm.connect.http.ProfileEndpoint.PROFILE_CONTENT_TYPE;
-import static org.restcomm.connect.http.ProfileEndpoint.PROFILE_SCHEMA_CONTENT_TYPE;
import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
@Path("/Profiles")
@ThreadSafe
@RolesAllowed(SUPER_ADMIN_ROLE)
@Singleton
-public class ProfileJsonEndpoint extends ProfileEndpoint{
+public class ProfileJsonEndpoint extends ProfileEndpoint {
@GET
@Produces(APPLICATION_JSON)
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SecuredEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SecuredEndpoint.java
index 6993ac21ad..b3d02daf40 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SecuredEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SecuredEndpoint.java
@@ -38,7 +38,6 @@
import org.restcomm.connect.extension.controller.ExtensionController;
import org.restcomm.connect.http.exceptions.AuthorizationException;
import org.restcomm.connect.http.exceptions.InsufficientPermission;
-import org.restcomm.connect.http.exceptions.NotAuthenticated;
import org.restcomm.connect.http.exceptions.OperatedAccountMissing;
import org.restcomm.connect.identity.AuthOutcome;
import org.restcomm.connect.identity.IdentityContext;
@@ -111,15 +110,6 @@ protected void init(final Configuration configuration) {
}
}
- /**
- * Grants general purpose access if any valid token exists in the request
- */
- protected void checkAuthenticatedAccount() {
- if (userIdentityContext.getEffectiveAccount() == null) {
- throw new NotAuthenticated();
- }
- }
-
/**
* Checks if the effective account is a super account (top level account)
* @return
@@ -185,8 +175,13 @@ protected void secure(final Account operatedAccount, final String permission) th
secure(operatedAccount, permission, SecuredType.SECURED_STANDARD);
}
+ /**
+ * @param operatedAccount
+ * @param permission
+ * @param type
+ * @throws AuthorizationException
+ */
protected void secure(final Account operatedAccount, final String permission, SecuredType type) throws AuthorizationException {
- checkAuthenticatedAccount();
checkPermission(permission); // check an authenticated account allowed to do "permission" is available
checkOrganization(operatedAccount); // check if valid organization is attached with this account.
if (operatedAccount == null) {
@@ -226,8 +221,13 @@ private void checkOrganization(Account account) throws IllegalStateException {
}
}
+ /**
+ * @param operatedAccount
+ * @param resourceAccountSid
+ * @param type
+ * @throws AuthorizationException
+ */
protected void secure(final Account operatedAccount, final Sid resourceAccountSid, SecuredType type) throws AuthorizationException {
- checkAuthenticatedAccount();
if (operatedAccount == null) {
// if operatedAccount is NULL, we'll probably return a 404. But let's handle that in a central place.
throw new OperatedAccountMissing();
@@ -446,5 +446,4 @@ protected boolean executePostApiAction(final ApiRequest apiRequest) {
ExtensionController ec = ExtensionController.getInstance();
return ec.executePostApiAction(apiRequest, extensions).isAllowed();
}
-
}
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupervisorEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupervisorEndpoint.java
index 080a74504f..ee46fce07f 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupervisorEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupervisorEndpoint.java
@@ -109,8 +109,6 @@ public void init() {
protected Response pong(final String accountSid, final MediaType responseType) {
//following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
CallDetailRecordFilter filterForTotal;
try {
filterForTotal = new CallDetailRecordFilter("", null, null, null, null, null,null,
@@ -131,8 +129,6 @@ protected Response pong(final String accountSid, final MediaType responseType) {
protected Response getMetrics(final String accountSid, final UriInfo info, final MediaType responseType) {
//following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
boolean withLiveCallDetails = false;
boolean withMgcpStats = false;
if (info != null && info.getQueryParameters().containsKey("LiveCallDetails") ) {
@@ -172,8 +168,6 @@ protected Response getMetrics(final String accountSid, final UriInfo info, final
protected Response getLiveCalls(final String accountSid, final MediaType responseType) {
//following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
LiveCallsDetails callDetails;
try {
final Timeout expires = new Timeout(Duration.create(5, TimeUnit.SECONDS));
@@ -204,8 +198,6 @@ protected Response getLiveCalls(final String accountSid, final MediaType respons
//Register a remote location where Restcomm will send monitoring updates
protected Response registerForUpdates(final String accountSid, final UriInfo info, MediaType responseType) {
//following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
boolean withLiveCallDetails = false;
boolean withMgcpStats = false;
if (info != null && info.getQueryParameters().containsKey("LiveCallDetails") ) {
@@ -243,8 +235,6 @@ protected Response registerForUpdates(final String accountSid, final UriInfo inf
//Register a remote location where Restcomm will send monitoring updates for a specific Call
protected Response registerForCallUpdates(final String accountSid, final String callSid, final MultivaluedMap data, MediaType responseType) {
//following 2 things are enough to grant access: 1. a valid authentication token is present. 2 it is a super admin.
- checkAuthenticatedAccount();
- allowOnlySuperAdmin();
final String url = data.getFirst("Url");
final String refresh = data.getFirst("Refresh");
boolean withLiveCallDetails = false;
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupservisorJsonEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupservisorJsonEndpoint.java
index 9a5f703b4b..068df9aa0a 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupservisorJsonEndpoint.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SupservisorJsonEndpoint.java
@@ -32,6 +32,9 @@
import javax.ws.rs.core.UriInfo;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static org.restcomm.connect.http.security.AccountPrincipal.SUPER_ADMIN_ROLE;
+
+import javax.annotation.security.RolesAllowed;
/**
* @author gvagenas
@@ -39,6 +42,7 @@
*/
@Path("/Accounts/{accountSid}/Supervisor.json")
@ThreadSafe
+@RolesAllowed(SUPER_ADMIN_ROLE)
public class SupservisorJsonEndpoint extends SupervisorEndpoint{
public SupservisorJsonEndpoint() {
diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/security/SecurityFilter.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/security/SecurityFilter.java
index bc8414a251..57922342a4 100644
--- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/security/SecurityFilter.java
+++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/security/SecurityFilter.java
@@ -19,22 +19,29 @@
*/
package org.restcomm.connect.http.security;
-import com.sun.jersey.spi.container.ContainerRequest;
-import com.sun.jersey.spi.container.ContainerRequestFilter;
-import org.apache.log4j.Logger;
+import static javax.ws.rs.core.Response.status;
+
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;
+
+import org.apache.log4j.Logger;
import org.restcomm.connect.dao.AccountsDao;
import org.restcomm.connect.dao.DaoManager;
-import org.restcomm.connect.dao.OrganizationsDao;
-import org.restcomm.connect.identity.IdentityContext;
+import org.restcomm.connect.dao.entities.Account;
import org.restcomm.connect.identity.UserIdentityContext;
+import com.sun.jersey.spi.container.ContainerRequest;
+import com.sun.jersey.spi.container.ContainerRequestFilter;
+
@Provider
public class SecurityFilter implements ContainerRequestFilter {
private final Logger logger = Logger.getLogger(SecurityFilter.class);
+ private static final String PATTERN_FOR_RECORDING_FILE_PATH=".*Accounts/.*/Recordings/RE.*[.mp4|.wav]";
@Context
private HttpServletRequest servletRequest;
@@ -42,19 +49,37 @@ public class SecurityFilter implements ContainerRequestFilter {
// We return Access-* headers only in case allowedOrigin is present and equals to the 'Origin' header.
@Override
public ContainerRequest filter(ContainerRequest cr) {
- //TODO only apply to Profiles endpoint by now
- if (cr.getPath().contains("Profiles")) {
- final DaoManager storage = (DaoManager) servletRequest.getServletContext().getAttribute(DaoManager.class.getName());
- AccountsDao accountsDao = storage.getAccountsDao();
- OrganizationsDao organizationsDao = storage.getOrganizationsDao();
- IdentityContext identityContext = (IdentityContext) servletRequest.getServletContext().getAttribute(IdentityContext.class.getName());
- UserIdentityContext userIdentityContext = new UserIdentityContext(servletRequest, accountsDao);
- String scheme = cr.getAuthenticationScheme();
- AccountPrincipal aPrincipal = new AccountPrincipal(userIdentityContext);
- cr.setSecurityContext(new RCSecContext(aPrincipal, scheme));
- return cr;
+ final DaoManager storage = (DaoManager) servletRequest.getServletContext().getAttribute(DaoManager.class.getName());
+ AccountsDao accountsDao = storage.getAccountsDao();
+ UserIdentityContext userIdentityContext = new UserIdentityContext(servletRequest, accountsDao);
+ // exclude recording file https://telestax.atlassian.net/browse/RESTCOMM-1736
+ logger.info("cr.getPath(): "+cr.getPath());
+ if (!cr.getPath().matches(PATTERN_FOR_RECORDING_FILE_PATH)) {
+ checkAuthenticatedAccount(userIdentityContext);
+ filterClosedAccounts(userIdentityContext);
}
+ String scheme = cr.getAuthenticationScheme();
+ AccountPrincipal aPrincipal = new AccountPrincipal(userIdentityContext);
+ cr.setSecurityContext(new RCSecContext(aPrincipal, scheme));
return cr;
}
+ /**
+ * Grants general purpose access if any valid token exists in the request
+ */
+ protected void checkAuthenticatedAccount(UserIdentityContext userIdentityContext) {
+ if (userIdentityContext.getEffectiveAccount() == null) {
+ throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic realm=\"Restcomm realm\"").build());
+ }
+ }
+
+ /**
+ * filter out accounts that are not active
+ * @param userIdentityContext
+ */
+ protected void filterClosedAccounts(UserIdentityContext userIdentityContext){
+ if(userIdentityContext.getEffectiveAccount() != null && !userIdentityContext.getEffectiveAccount().getStatus().equals(Account.Status.ACTIVE)){
+ throw new WebApplicationException(status(Status.FORBIDDEN).entity("Provided Account is not active").build());
+ }
+ }
}
diff --git a/restcomm/restcomm.http/src/test/java/org/restcomm/connect/http/AccountsEndpointMockedTest.java b/restcomm/restcomm.http/src/test/java/org/restcomm/connect/http/AccountsEndpointMockedTest.java
index 9158e641f0..674504a185 100644
--- a/restcomm/restcomm.http/src/test/java/org/restcomm/connect/http/AccountsEndpointMockedTest.java
+++ b/restcomm/restcomm.http/src/test/java/org/restcomm/connect/http/AccountsEndpointMockedTest.java
@@ -40,14 +40,4 @@ public void endpointInitializedAndBasicAuthorizationWork() throws ConfigurationE
endpoint.init();
}
- @Test(expected=NotAuthenticated.class)
- public void requestMissingAuthorizationIsRejected() {
- init(); // setup default mocking values
- when(request.getHeader("Authorization")).thenReturn(null); // override Authorization header to null
- AccountsEndpoint endpoint = new AccountsEndpoint(servletContext,request);
- endpoint.init();
- //use endpoint to cause the exception
- endpoint.getAccounts(null, MediaType.TEXT_XML_TYPE);
- }
-
}
diff --git a/restcomm/restcomm.testsuite/src/main/java/org/restcomm/connect/testsuite/provisioning/number/vi/RestcommIncomingPhoneNumberTool.java b/restcomm/restcomm.testsuite/src/main/java/org/restcomm/connect/testsuite/provisioning/number/vi/RestcommIncomingPhoneNumberTool.java
index c5d1cde2fe..de0b67005c 100644
--- a/restcomm/restcomm.testsuite/src/main/java/org/restcomm/connect/testsuite/provisioning/number/vi/RestcommIncomingPhoneNumberTool.java
+++ b/restcomm/restcomm.testsuite/src/main/java/org/restcomm/connect/testsuite/provisioning/number/vi/RestcommIncomingPhoneNumberTool.java
@@ -23,6 +23,7 @@
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;
@@ -161,4 +162,28 @@ public JsonObject getIncomingPhoneNumbersUsingFilter(String deploymentUrl, Strin
return jsonObject;
}
+ public ClientResponse getIncomingPhonNumberClientResponse(String deploymentUrl, String username, String authToken){
+ Client jerseyClient = Client.create();
+ jerseyClient.addFilter(new HTTPBasicAuthFilter(username, authToken));
+ String url = getAccountsUrl(deploymentUrl, username, true);
+ WebResource webResource = jerseyClient.resource(url);
+ return webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).accept("application/json").post(ClientResponse.class);
+
+ }
+
+ public ClientResponse purchaseProviderNumber( String deploymentUrl, String username, String authToken, String phoneNumber, String voiceUrl, String voiceMethod, String friendlyName ){
+ Client jerseyClient = Client.create();
+ jerseyClient.addFilter(new HTTPBasicAuthFilter(username, authToken));
+
+ String provisioningURL = getAccountsUrl(deploymentUrl, username, true);
+ WebResource webResource = jerseyClient.resource(provisioningURL);
+
+ MultivaluedMap formData = new MultivaluedMapImpl();
+ formData.add("PhoneNumber", phoneNumber);
+ formData.add("VoiceUrl", voiceUrl);
+ formData.add("FriendlyName", friendlyName);
+ formData.add("VoiceMethod", voiceMethod);
+ return webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).accept("application/json").post(ClientResponse.class, formData);
+ }
+
}
diff --git a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/AccountsEndpointClosingTest.java b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/AccountsEndpointClosingTest.java
index 51ee3ce46c..63caf0f910 100644
--- a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/AccountsEndpointClosingTest.java
+++ b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/AccountsEndpointClosingTest.java
@@ -21,11 +21,16 @@
package org.restcomm.connect.testsuite.http;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonParser;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import junit.framework.Assert;
+
+import org.apache.http.HttpResponse;
import org.apache.log4j.Logger;
import org.jboss.arquillian.container.test.api.Deployer;
import org.jboss.arquillian.container.test.api.Deployment;
@@ -40,7 +45,10 @@
import org.junit.runner.RunWith;
import org.restcomm.connect.commons.Version;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+
+import java.io.IOException;
import java.net.URL;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
@@ -49,10 +57,16 @@
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import org.junit.experimental.categories.Category;
import org.restcomm.connect.commons.annotations.UnstableTests;
+import org.restcomm.connect.testsuite.provisioning.number.vi.AvailablePhoneNumbersEndpointTestUtils;
+import org.restcomm.connect.testsuite.provisioning.number.vi.RestcommIncomingPhoneNumberTool;
/**
* @author otsakir@gmail.com - Orestis Tsakiridis
diff --git a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/CorsRelaxTest.java b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/CorsRelaxTest.java
index 045562688f..b9806ecdca 100644
--- a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/CorsRelaxTest.java
+++ b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/CorsRelaxTest.java
@@ -32,6 +32,7 @@
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.archive.ShrinkWrapMaven;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.restcomm.connect.commons.Version;
@@ -44,8 +45,14 @@
* Currently it only tests Accounts endpoint where CORS-relax logic has been applied
*
* @author otsakir@gmail.com - Orestis Tsakiridis
+ *
+ * It was written for the case when restcomm should accept CORS requests and return the appropriate headers.
+ * Initially that would happen if restcomm would be in a different domain from RVD.
+ * Later, we decided to put everything (restcomm and RVD) behind the same domain.
+ * So, relaxing CORS restrictions is not really needed
*/
@RunWith(Arquillian.class)
+@Ignore
public class CorsRelaxTest extends EndpointTest {
private final static Logger logger = Logger.getLogger(CorsRelaxTest.class.getName());
diff --git a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/ProfilesEndpointTest.java b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/ProfilesEndpointTest.java
index 92ff779e8b..2b1df5724a 100644
--- a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/ProfilesEndpointTest.java
+++ b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/ProfilesEndpointTest.java
@@ -10,6 +10,8 @@
import java.net.URISyntaxException;
import java.net.URL;
+import javax.ws.rs.core.MediaType;
+
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.log4j.Logger;
@@ -35,8 +37,11 @@
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResourceLinkHeaders;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.header.LinkHeader;
/**
@@ -523,12 +528,7 @@ public void testRemovalOfAssociationOnDeleteProfile() throws ClientProtocolExcep
@Test
public void getProfileSchemaTest() throws Exception {
- URL schemaURL = new URL(RestcommProfilesTool.getInstance().getProfileSchemaUrl(deploymentUrl.toString()));
- final JsonNode schemaNode = JsonLoader.fromURL(schemaURL);
- final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
- final JsonSchema schema = factory.getJsonSchema(schemaNode);
-
- ClientResponse clientResponse = RestcommProfilesTool.getInstance().getProfileSchema(deploymentUrl.toString(), SUPER_ADMIN_ACCOUNT_SID, AUTH_TOKEN);
+ ClientResponse clientResponse = RestcommProfilesTool.getInstance().getProfileSchema(deploymentUrl.toString(), SUPER_ADMIN_ACCOUNT_SID, AUTH_TOKEN);
assertEquals(200, clientResponse.getStatus());
String str = clientResponse.getEntity(String.class);
assertNotNull(str);
diff --git a/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/RestcommAPIEndpointSecurityTest.java b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/RestcommAPIEndpointSecurityTest.java
new file mode 100644
index 0000000000..8be780f0fb
--- /dev/null
+++ b/restcomm/restcomm.testsuite/src/test/java/org/restcomm/connect/testsuite/http/RestcommAPIEndpointSecurityTest.java
@@ -0,0 +1,217 @@
+package org.restcomm.connect.testsuite.http;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.log4j.Logger;
+import org.jboss.arquillian.container.test.api.Deployer;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.archive.ShrinkWrapMaven;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.restcomm.connect.commons.Version;
+import org.restcomm.connect.commons.annotations.FeatureExpTests;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+
+@RunWith(Arquillian.class)
+public class RestcommAPIEndpointSecurityTest {
+ private final static Logger logger = Logger.getLogger(RestcommAPIEndpointSecurityTest.class.getName());
+
+ private static final String version = Version.getVersion();
+
+ @ArquillianResource
+ private Deployer deployer;
+ @ArquillianResource
+ URL deploymentUrl;
+
+ private static final String SUPER_ADMIN_ACCOUNT_SID = "ACae6e420f425248d6a26948c17a9e2acf";
+ private static final String CLOSED_ACCOUNT_SID="ACA3000000000000000000000000000000";
+ private static final String SUSPENDED_ACCOUNT_SID="ACA4000000000000000000000000000000";
+ private static final String AUTH_TOKEN = "77f8c12cc7b8f8423e5c38b035249166";
+ private static final String RESOURCE_SID = "PRae6e420f425248d6a26948c17a9e2acf";
+ private static final String GENERIC_ENDPOINT = "/2012-04-24/";
+ private static final String PROFILE_ENDPOINT = "/2012-04-24/Profiles";
+ private static final String ACCOUNT_ENDPOINT = "/2012-04-24/Accounts";
+ private static final String ORGANIZATION_ENDPOINT = "/2012-04-24/Organizations";
+ private static final String CLIENTS_ENDPOINT = "/2012-04-24/Accounts/"+SUPER_ADMIN_ACCOUNT_SID+"/Clients";
+ private static final String RECORDINGS_ENDPOINT_FILE_PATH = "/2012-04-24/Accounts/"+SUPER_ADMIN_ACCOUNT_SID+"/Recordings/REc267d9cdcd0f4623a54abedf8e3d8835";
+ private static final String RECORDINGS_ENDPOINT = "/2012-04-24/Accounts/"+SUPER_ADMIN_ACCOUNT_SID+"/Recordings";
+ private static final String RECORDINGS_ENDPOINT_FILE_FULL_PATH = "http://127.0.0.1:8080/restcomm/2012-04-24/Accounts/"+SUPER_ADMIN_ACCOUNT_SID+"/Recordings/REc267d9cdcd0f4623a54abedf8e3d8835";
+
+ /**
+ * this test will try to access generic EP Without Authentication or invalid token
+ */
+ @Test
+ public void genericSecurityTest(){
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+GENERIC_ENDPOINT));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+GENERIC_ENDPOINT));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+GENERIC_ENDPOINT, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+GENERIC_ENDPOINT, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+ }
+ /**
+ * this test will try to access org EP Without Authentication or invalid token
+ */
+ @Test
+ @Category(FeatureExpTests.class)
+ public void organizationSecurityTest(){
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+ORGANIZATION_ENDPOINT+"/"+RESOURCE_SID));
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+ORGANIZATION_ENDPOINT));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+ORGANIZATION_ENDPOINT));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+ORGANIZATION_ENDPOINT, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+ORGANIZATION_ENDPOINT, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+ }
+
+ /**
+ * this test will try to access acc EP Without Authentication or invalid token
+ */
+ @Test
+ @Category(FeatureExpTests.class)
+ public void accountSecurityTest(){
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+ACCOUNT_ENDPOINT+"/"+RESOURCE_SID));
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+ACCOUNT_ENDPOINT));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+ACCOUNT_ENDPOINT));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+ACCOUNT_ENDPOINT, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+ACCOUNT_ENDPOINT, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+ }
+
+
+ /**
+ * this test will try to access profile EP Without Authentication or invalid token
+ */
+ @Test
+ @Category(FeatureExpTests.class)
+ public void profileSecurityTest(){
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+PROFILE_ENDPOINT+"/"+RESOURCE_SID));
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+PROFILE_ENDPOINT));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+PROFILE_ENDPOINT));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+PROFILE_ENDPOINT, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+PROFILE_ENDPOINT, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+ }
+
+ /**
+ * this test will try to access client EP Without Authentication or invalid token
+ */
+ @Test
+ @Category(FeatureExpTests.class)
+ public void clientSecurityTest(){
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+CLIENTS_ENDPOINT+"/"+RESOURCE_SID));
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+CLIENTS_ENDPOINT));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+CLIENTS_ENDPOINT));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+CLIENTS_ENDPOINT, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+CLIENTS_ENDPOINT, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+ }
+
+ /**
+ * this test will try to access recording endpoint
+ * we allow audio video file to be accessed, but recording list and single resource description is protected
+ * we will need to change this test if https://telestax.atlassian.net/browse/RESTCOMM-1736 is implemented
+ * @throws IOException
+ */
+ @Test
+ public void recordingSecurityTest() throws IOException{
+ //recording list is protected
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+RECORDINGS_ENDPOINT));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+
+ //recording resource is protected
+ assertEquals(401, performUnautherizedRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH));
+ assertEquals(401, performRequestWithInvalidToken(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH, CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(403, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH, SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+
+ //recording audio file is not protected, we consider 404 equivalent to 200 as that means we already bypassed 401 and 403 and the fact that file does not exists
+ assertEquals(404, performUnautherizedRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".wav"));
+ assertEquals(404, performRequestWithInvalidToken(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".wav"));
+ assertEquals(404, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".wav", CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(404, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".wav", SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+
+ //recording video file is not protected, we consider 404 equivalent to 200 as that means we already bypassed 401 and 403 and the fact that file does not exists
+ assertEquals(404, performUnautherizedRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".mp4"));
+ assertEquals(404, performRequestWithInvalidToken(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".mp4"));
+ assertEquals(404, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".mp4", CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ assertEquals(404, performApiRequest(deploymentUrl.toString()+RECORDINGS_ENDPOINT_FILE_PATH+".mp4", SUSPENDED_ACCOUNT_SID, AUTH_TOKEN));
+
+ //access by simple http url connection
+ URL url = new URL(RECORDINGS_ENDPOINT_FILE_FULL_PATH+".wav");
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.connect();
+ assertEquals(404, connection.getResponseCode());
+ }
+
+ /**
+ * perform api Request with account
+ *
+ * @param endpointUrl
+ * @return
+ */
+ private int performApiRequest(String endpointUrl, String account, String auth){
+ Client jerseyClient = Client.create();
+ jerseyClient.addFilter(new HTTPBasicAuthFilter(CLOSED_ACCOUNT_SID, AUTH_TOKEN));
+ WebResource webResource = jerseyClient.resource(endpointUrl);
+ ClientResponse clientResponse = webResource.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML).get(ClientResponse.class);
+ return clientResponse.getStatus();
+ }
+
+ /**
+ * performUnautherizedRequest with no authentication
+ *
+ * @param endpointUrl
+ * @return
+ */
+ private int performUnautherizedRequest(String endpointUrl){
+ Client jerseyClient = Client.create();
+ WebResource webResource = jerseyClient.resource(endpointUrl);
+ ClientResponse clientResponse = webResource.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML).get(ClientResponse.class);
+ return clientResponse.getStatus();
+ }
+
+ /**
+ * perform request with Invalid Token
+ * @param endpointUrl
+ * @return
+ */
+ private int performRequestWithInvalidToken(String endpointUrl){
+ Client jerseyClient = Client.create();
+ jerseyClient.addFilter(new HTTPBasicAuthFilter(SUPER_ADMIN_ACCOUNT_SID, "wrongauthtoken"));
+ WebResource webResource = jerseyClient.resource(endpointUrl);
+ ClientResponse clientResponse = webResource.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML).get(ClientResponse.class);
+ return clientResponse.getStatus();
+ }
+
+ @Deployment(name = "RestcommAPIEndpointSecurityTest", managed = true, testable = false)
+ public static WebArchive createWebArchiveNoGw() {
+ logger.info("Packaging Test App");
+ logger.info("version");
+ WebArchive archive = ShrinkWrap.create(WebArchive.class, "restcomm.war");
+ final WebArchive restcommArchive = ShrinkWrapMaven.resolver()
+ .resolve("org.restcomm:restcomm-connect.application:war:" + version).withoutTransitivity()
+ .asSingle(WebArchive.class);
+ archive = archive.merge(restcommArchive);
+ archive.delete("/WEB-INF/sip.xml");
+ archive.delete("/WEB-INF/conf/restcomm.xml");
+ archive.delete("/WEB-INF/data/hsql/restcomm.script");
+ archive.addAsWebInfResource("sip.xml");
+ archive.addAsWebInfResource("restcomm.xml", "conf/restcomm.xml");
+ archive.addAsWebInfResource("restcomm.script_accounts_test", "data/hsql/restcomm.script");
+ logger.info("Packaged Test App");
+ return archive;
+ }
+}
diff --git a/restcomm/restcomm.testsuite/src/test/resources/restcomm.script_accounts_test b/restcomm/restcomm.testsuite/src/test/resources/restcomm.script_accounts_test
index 83ec87ee05..762bd1a66a 100644
--- a/restcomm/restcomm.testsuite/src/test/resources/restcomm.script_accounts_test
+++ b/restcomm/restcomm.testsuite/src/test/resources/restcomm.script_accounts_test
@@ -33,6 +33,8 @@ INSERT INTO "restcomm_organizations" VALUES('ORafbe225ad37541eba518a74248f0ac4c'
INSERT INTO "restcomm_organizations" VALUES('ORafbe225ad37541eba518a74248f0ac4d', 'org1.restcomm.com', '2017-04-19 00:00:00.000000000','2017-04-19 00:00:00.000000000', 'active')
INSERT INTO "restcomm_organizations" VALUES('ORafbe225ad37541eba518a74248f0ac4e', 'org2.restcomm.com', '2017-04-19 00:00:00.000000000','2017-04-19 00:00:00.000000000', 'closed')
INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2acf','2012-04-24 22:51:29.372000000','2012-04-24 22:51:29.372000000','administrator@company.com','Default Administrator Account',NULL,'Full','active','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf','ORafbe225ad37541eba518a74248f0ac4c')
+INSERT INTO "restcomm_accounts" VALUES('ACA3000000000000000000000000000000','2012-04-24 22:51:29.372000000','2012-04-24 22:51:29.372000000','childA3@company.com','childA3','ACA0000000000000000000000000000000','Full','closed','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACA3000000000000000000000000000000','ORafbe225ad37541eba518a74248f0ac4c')
+INSERT INTO "restcomm_accounts" VALUES('ACA4000000000000000000000000000000','2012-04-24 22:51:29.372000000','2012-04-24 22:51:29.372000000','childA3@company.com','childA3','ACA0000000000000000000000000000000','Full','suspended','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACA3000000000000000000000000000000','ORafbe225ad37541eba518a74248f0ac4c')
INSERT INTO "restcomm_accounts" VALUES('AC574d775522c96f9aacacc5ca60c8c74f','2012-04-24 22:51:29.372000000','2012-04-24 22:51:29.372000000','child@company.com','Child Account','ACae6e420f425248d6a26948c17a9e2acf','Full','active','77f8c12cc7b8f8423e5c38b035249166','Developer','/2012-04-24/Accounts/AC574d775522c96f9aacacc5ca60c8c74f','ORafbe225ad37541eba518a74248f0ac4c')
INSERT INTO "restcomm_accounts" VALUES('AC574d775522c96f9aacacc5ca60c8c111','2012-04-24 22:51:29.372000000','2012-04-24 22:51:29.372000000','child2@company.com','Child 2 Account','ACae6e420f425248d6a26948c17a9e2acf','Full','active','77f8c12cc7b8f8423e5c38b035249166','Developer','/2012-04-24/Accounts/AC574d775522c96f9aacacc5ca60c8c74f','ORafbe225ad37541eba518a74248f0ac4d')
INSERT INTO "restcomm_accounts" VALUES('AC574d775522c96f9aacacc5ca60c8c74g','2012-04-24 22:51:29.372000000','2012-04-24 22:51:29.372000000','admin@company.com','Admin Account','ACae6e420f425248d6a26948c17a9e2acf','Full','active','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/AC574d775522c96f9aacacc5ca60c8c74g','ORafbe225ad37541eba518a74248f0ac4c')