Merge pull request 'Implementing a component to invoke APIM publisher REST API (Scope mapping)' (#104) from pasindu/device-mgt-core:scopeMapAPILayer into master

Reviewed-on: community/device-mgt-core#104
device-info-config
Charitha Goonetilleke 2 years ago
commit 99df875fb3

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.26-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.device.mgt.core.apimgt.extension.rest.api</artifactId>
<packaging>bundle</packaging>
<name>Entgra - Device Management Extension for APIM REST API</name>
<description>Entgra - Device Management Extension for APIM REST API</description>
<url>https://entgra.io</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.impl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>5.1.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>Publisher API Management Bundle</Bundle-Description>
<Private-Package>
io.entgra.device.mgt.core.apimgt.extension.rest.api.internal
</Private-Package>
<Export-Package>
!io.entgra.device.mgt.core.apimgt.extension.rest.api.internal,
io.entgra.device.mgt.core.apimgt.extension.rest.api.*
</Export-Package>
<Import-Package>
org.osgi.framework.*;version="${imp.package.version.osgi.framework}",
org.osgi.service.*;version="${imp.package.version.osgi.service}",
org.wso2.carbon.core;version="4.6",
org.wso2.carbon.core.util;version="4.6",
org.apache.commons.ssl,
org.wso2.carbon.apimgt.api.model,
okhttp3.*,
org.wso2.carbon.apimgt.impl;version="${carbon.api.mgt.version.range}",
org.wso2.carbon.apimgt.impl.utils;version="${carbon.api.mgt.version.range}",
org.wso2.carbon.apimgt.impl.internal;version="${carbon.api.mgt.version.range}",
org.json
</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,33 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
public interface APIApplicationServices {
APIApplicationKey createAndRetrieveApplicationCredentials() throws APIServicesException;
AccessTokenInfo generateAccessTokenFromRegisteredApplication(String clientId, String clientSecret) throws APIServicesException;
AccessTokenInfo generateAccessTokenFromRefreshToken(String refreshToken, String clientId, String clientSecret) throws APIServicesException;
}

@ -0,0 +1,128 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import com.google.gson.Gson;
import org.json.JSONObject;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.RequestBody;
import okhttp3.Credentials;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.impl.APIManagerConfiguration;
import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder;
import java.io.IOException;
public class APIApplicationServicesImpl implements APIApplicationServices {
private static final Log log = LogFactory.getLog(APIApplicationServicesImpl.class);
private static final OkHttpClient client = new OkHttpClient(HttpsTrustManagerUtils.getSSLClient().newBuilder());
private static final Gson gson = new Gson();
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
String msg = null;
APIManagerConfiguration config = ServiceReferenceHolder.getInstance().
getAPIManagerConfigurationService().getAPIManagerConfiguration();
@Override
public APIApplicationKey createAndRetrieveApplicationCredentials()
throws APIServicesException {
String applicationEndpoint = config.getFirstProperty(Constants.DCR_END_POINT);
String serverUser = config.getFirstProperty(Constants.SERVER_USER);
String serverPassword = config.getFirstProperty(Constants.SERVER_PASSWORD);
JSONObject jsonObject = new JSONObject();
jsonObject.put("callbackUrl", Constants.EMPTY_STRING);
jsonObject.put("clientName", Constants.CLIENT_NAME);
jsonObject.put("grantType", Constants.GRANT_TYPE);
jsonObject.put("owner", serverUser);
jsonObject.put("saasApp", true);
RequestBody requestBody = RequestBody.Companion.create(jsonObject.toString(), JSON);
Request request = new Request.Builder()
.url(applicationEndpoint)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(serverUser, serverPassword))
.post(requestBody)
.build();
try {
Response response = client.newCall(request).execute();
return gson.fromJson(response.body().string(), APIApplicationKey.class);
} catch (IOException e) {
msg = "Error occurred while processing the response";
log.error(msg, e);
throw new APIServicesException(e);
}
}
@Override
public AccessTokenInfo generateAccessTokenFromRegisteredApplication(String consumerKey, String consumerSecret)
throws APIServicesException {
String userName = config.getFirstProperty(Constants.SERVER_USER);
String userPassword = config.getFirstProperty(Constants.SERVER_PASSWORD);
JSONObject params = new JSONObject();
params.put(Constants.GRANT_TYPE_PARAM_NAME, Constants.PASSWORD_GRANT_TYPE);
params.put(Constants.PASSWORD_GRANT_TYPE_USERNAME, userName);
params.put(Constants.PASSWORD_GRANT_TYPE_PASSWORD, userPassword);
params.put(Constants.SCOPE_PARAM_NAME, Constants.SCOPES);
return getToken(params, consumerKey, consumerSecret);
}
@Override
public AccessTokenInfo generateAccessTokenFromRefreshToken(String refreshToken, String consumerKey, String consumerSecret)
throws APIServicesException {
JSONObject params = new JSONObject();
params.put(Constants.GRANT_TYPE_PARAM_NAME, Constants.REFRESH_TOKEN_GRANT_TYPE);
params.put(Constants.REFRESH_TOKEN_GRANT_TYPE_PARAM_NAME, refreshToken);
params.put(Constants.SCOPE_PARAM_NAME, Constants.SCOPES);
return getToken(params, consumerKey, consumerSecret);
}
public AccessTokenInfo getToken(JSONObject nameValuePairs, String clientId, String clientSecret)
throws APIServicesException {
String tokenEndPoint = config.getFirstProperty(Constants.TOKE_END_POINT);
RequestBody requestBody = RequestBody.Companion.create(nameValuePairs.toString(), JSON);
Request request = new Request.Builder()
.url(tokenEndPoint)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(clientId, clientSecret))
.post(requestBody)
.build();
try {
Response response = client.newCall(request).execute();
return gson.fromJson(response.body().string(), AccessTokenInfo.class);
} catch (IOException e) {
msg = "Error occurred while processing the response";
log.error(msg, e);
throw new APIServicesException(e);
}
}
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.api.model.Scope;
public interface PublisherRESTAPIServices {
JSONObject getScopes(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean isSharedScopeNameExists(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String key)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean updateSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
}

@ -0,0 +1,178 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.ScopeUtils;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.RequestBody;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.ssl.Base64;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.api.model.Scope;
import java.io.IOException;
public class PublisherRESTAPIServicesImpl implements PublisherRESTAPIServices {
private static final Log log = LogFactory.getLog(PublisherRESTAPIServicesImpl.class);
private static final OkHttpClient client = new OkHttpClient(HttpsTrustManagerUtils.getSSLClient().newBuilder());
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final String host = System.getProperty(Constants.IOT_CORE_HOST);
private static final String port = System.getProperty(Constants.IOT_CORE_HTTPS_PORT);
@Override
public JSONObject getScopes(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getAllScopesUrl = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host + Constants.COLON
+ port + Constants.GET_ALL_SCOPES;
Request request = new Request.Builder()
.url(getAllScopesUrl)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ accessTokenInfo.getAccess_token())
.get()
.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
JSONObject jsonObject = new JSONObject(response.body().string());
return jsonObject;
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(accessTokenInfo.getRefresh_token(),
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
//TODO: max attempt count
return getScopes(apiApplicationKey, refreshedAccessToken);
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
log.error(msg, e);
throw new APIServicesException(e);
}
}
@Override
public boolean isSharedScopeNameExists(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String key)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String keyValue = new String(Base64.encodeBase64((key).getBytes())).replace(Constants.QUERY_KEY_VALUE_SEPARATOR,
Constants.EMPTY_STRING);
String getScopeUrl = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host + Constants.COLON
+ port + Constants.GET_SCOPE + keyValue;
Request request = new Request.Builder()
.url(getScopeUrl)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ accessTokenInfo.getAccess_token())
.head()
.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return true;
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(accessTokenInfo.getRefresh_token(),
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
//TODO: max attempt count
return isSharedScopeNameExists(apiApplicationKey, refreshedAccessToken, key);
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
log.error(msg, e);
throw new APIServicesException(e);
}
}
@Override
public boolean updateSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String updateScopeUrl = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host
+ Constants.COLON + port + Constants.GET_SCOPE + scope.getId();
ScopeUtils scopeUtil = new ScopeUtils();
scopeUtil.setKey(scope.getKey());
scopeUtil.setName(scope.getName());
scopeUtil.setDescription(scope.getDescription());
scopeUtil.setRoles(scope.getRoles());
String scopeString = scopeUtil.toJSON();
RequestBody requestBody = RequestBody.create(JSON, scopeString);
Request request = new Request.Builder()
.url(updateScopeUrl)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ accessTokenInfo.getAccess_token())
.put(requestBody)
.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return true;
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(accessTokenInfo.getRefresh_token(),
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
//TODO: max attempt count
return updateSharedScope(apiApplicationKey, refreshedAccessToken, scope);
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid scope object";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
log.error(msg, e);
throw new APIServicesException(e);
}
}
}

@ -0,0 +1,100 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.bean;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
private String callbackUrl;
private String clientName;
private String tokenScope;
private String owner;
private String grantType;
private String applicationType;
private boolean isSaasApp;
private static final String TAG = RegistrationProfile.class.getSimpleName();
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
public boolean isSaasApp() {
return isSaasApp;
}
public void setIsSaasApp(boolean isSaasApp) {
this.isSaasApp = isSaasApp;
}
public String toJSON() {
String jsonString =
"{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName +
"\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
"\", \"saasApp\" : " + isSaasApp + " }\n";
return jsonString;
}
}

@ -0,0 +1,67 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.constants;
public final class Constants {
private Constants() {
}
public static final String EMPTY_STRING = "";
public static final String CLIENT_NAME = "rest_api_publisher_code";
public static final String SERVER_USER = "WorkflowConfigurations.ServerUser";
public static final String SERVER_PASSWORD = "WorkflowConfigurations.ServerPassword";
public static final String GRANT_TYPE = "client_credentials password refresh_token";
public static final String REFRESH_TOKEN_GRANT_TYPE_PARAM_NAME = "refresh_token";
public static final String OAUTH_EXPIRES_IN = "expires_in";
public static final String OAUTH_TOKEN_SCOPE = "scope";
public static final String OAUTH_TOKEN_TYPE = "token_type";
public static final String REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
public static final String SCOPE_PARAM_NAME = "scope";
public static final String SCOPES = "apim:api_create apim:api_view apim:shared_scope_manage";
public static final String DCR_END_POINT = "WorkflowConfigurations.DCREndPoint";
public static final String TOKE_END_POINT = "WorkflowConfigurations.TokenEndPoint";
public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
public static final String CLIENT_ID = "clientId";
public static final String CLIENT_SECRET = "clientSecret";
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic ";
public static final String AUTHORIZATION_HEADER_PREFIX_BEARER = "Bearer ";
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String APPLICATION_JSON = "application/json";
public static final String PASSWORD_GRANT_TYPE = "password";
public static final String PASSWORD_GRANT_TYPE_USERNAME = "username";
public static final String PASSWORD_GRANT_TYPE_PASSWORD = "password";
public static final String PASSWORD_GRANT_TYPE_SCOPES = "scopes";
public static final String ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME = "access_token";
public static final String GRANT_TYPE_PARAM_NAME = "grant_type";
public static final String HTTPS_PROTOCOL = "https";
public static final String HTTP_PROTOCOL = "http";
public static final String SCHEME_SEPARATOR = "://";
public static final String COLON = ":";
public static final String QUERY_KEY_VALUE_SEPARATOR = "=";
public static final String IOT_CORE_HOST = "iot.core.host";
public static final String IOT_CORE_HTTPS_PORT = "iot.core.https.port";
public static final String GET_ALL_SCOPES = "/api/am/publisher/v2/scopes?limit=1000";
public static final String GET_SCOPE = "/api/am/publisher/v2/scopes/";
}

@ -0,0 +1,113 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.dto;
/**
* This holds the consumer application information that return from the register application endpoint
*/
public class APIApplicationKey {
private String clientName;
private String clientId;
private String clientSecret;
private String callBackURL;
private String isSaasApplication;
private String appOwner;
private String jsonString;
private String jsonAppAttribute;
private String tokenType;
public APIApplicationKey(String clientId, String clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getCallBackURL() {
return callBackURL;
}
public void setCallBackURL(String callBackURL) {
this.callBackURL = callBackURL;
}
public String getIsSaasApplication() {
return isSaasApplication;
}
public void setIsSaasApplication(String isSaasApplication) {
this.isSaasApplication = isSaasApplication;
}
public String getAppOwner() {
return appOwner;
}
public void setAppOwner(String appOwner) {
this.appOwner = appOwner;
}
public String getJsonString() {
return jsonString;
}
public void setJsonString(String jsonString) {
this.jsonString = jsonString;
}
public String getJsonAppAttribute() {
return jsonAppAttribute;
}
public void setJsonAppAttribute(String jsonAppAttribute) {
this.jsonAppAttribute = jsonAppAttribute;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
}

@ -0,0 +1,71 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.dto;
/**
* This holds the token information that return from the token endpoint.
*/
public class AccessTokenInfo {
private String token_type;
private long expires_in;
private String refresh_token;
private String access_token;
private String scope;
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public long getExpires_in() {
return expires_in;
}
public void setExpires_in(long expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
public class APIServicesException extends Exception {
public APIServicesException() {
super();
}
public APIServicesException(String message) {
super(message);
}
public APIServicesException(String message, Throwable cause) {
super(message);
}
public APIServicesException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Custom exception class for handling bad request exceptions.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
public class BadRequestException extends Exception {
private static final long serialVersionUID = -2387103750774855056L;
public BadRequestException(String errorMessage) {
super(errorMessage);
}
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Custom exception class for handling unexpected server response exceptions.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
public class UnexpectedResponseException extends Exception {
private static final long serialVersionUID = -2387103750774855056L;
public UnexpectedResponseException(String errorMessage) {
super(errorMessage);
}
}

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.internal;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService;
public class PublisherRESTAPIDataHolder {
private APIApplicationServices apiApplicationServices;
private APIManagerConfigurationService apiManagerConfigurationService;
private static PublisherRESTAPIDataHolder thisInstance = new PublisherRESTAPIDataHolder();
private PublisherRESTAPIDataHolder() {
}
static PublisherRESTAPIDataHolder getInstance() {
return thisInstance;
}
public APIApplicationServices getApiApplicationServices() {
return apiApplicationServices;
}
public void setApiApplicationServices(APIApplicationServices apiApplicationServices) {
this.apiApplicationServices = apiApplicationServices;
}
public void setAPIManagerConfiguration(APIManagerConfigurationService apiManagerConfigurationService) {
this.apiManagerConfigurationService = apiManagerConfigurationService;
}
public APIManagerConfigurationService getAPIManagerConfigurationService() {
if (apiManagerConfigurationService == null) {
throw new IllegalStateException("API Manager Configuration service is not initialized properly");
}
return apiManagerConfigurationService;
}
}

@ -0,0 +1,79 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.internal;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService;
/**
* @scr.component name="internal.io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServiceComponent"
* immediate="true"
* @scr.reference name="user.apimanagerconfigurationservice.default"
* interface="org.wso2.carbon.apimgt.impl.APIManagerConfigurationService"
* cardinality="1..1"
* policy="dynamic"
* bind="setAPIManagerConfigurationService"
* unbind="unsetAPIManagerConfigurationService"
*/
public class PublisherRESTAPIServiceComponent {
private static Log log = LogFactory.getLog(PublisherRESTAPIServiceComponent.class);
protected void activate(ComponentContext componentContext) {
if (log.isDebugEnabled()) {
log.debug("Initializing publisher API extension bundle");
}
try {
BundleContext bundleContext = componentContext.getBundleContext();
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
bundleContext.registerService(APIApplicationServices.class.getName(), apiApplicationServices, null);
PublisherRESTAPIDataHolder.getInstance().setApiApplicationServices(apiApplicationServices);
if (log.isDebugEnabled()) {
log.debug("API Application bundle has been successfully initialized");
}
} catch (Exception e) {
log.error("Error occurred while initializing API Application bundle", e);
}
}
protected void deactivate(ComponentContext componentContext) {
//do nothing
}
protected void setAPIManagerConfigurationService(APIManagerConfigurationService apiManagerConfigurationService) {
if (log.isDebugEnabled()) {
log.debug("Setting API Manager Configuration Service");
}
PublisherRESTAPIDataHolder.getInstance().setAPIManagerConfiguration(apiManagerConfigurationService);
}
protected void unsetAPIManagerConfigurationService(APIManagerConfigurationService apiManagerConfigurationService) {
if (log.isDebugEnabled()) {
log.debug("Unsetting API Manager Configuration Service");
}
PublisherRESTAPIDataHolder.getInstance().setAPIManagerConfiguration(null);
}
}

@ -0,0 +1,234 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.util;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.SSLSession;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.HostnameVerifier;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class HttpsTrustManagerUtils {
private static final Log log = LogFactory.getLog(HttpsTrustManagerUtils.class);
private static final String KEY_STORE_TYPE = "JKS";
/**
* Default truststore type of the client
*/
private static final String TRUST_STORE_TYPE = "JKS";
/**
* Default keymanager type of the client
*/
private static final String KEY_MANAGER_TYPE = "SunX509"; //Default Key Manager Type
/**
* Default trustmanager type of the client
*/
private static final String TRUST_MANAGER_TYPE = "SunX509"; //Default Trust Manager Type
private static final String SSLV3 = "SSLv3";
private static final String DEFAULT_HOST = "localhost";
private static final String DEFAULT_HOST_IP = "127.0.0.1";
private static final int TIMEOUT = 100;
public static OkHttpClient getSSLClient() {
boolean isIgnoreHostnameVerification = Boolean.parseBoolean(System.getProperty("org.wso2"
+ ".ignoreHostnameVerification"));
OkHttpClient okHttpClient;
final String proxyHost = System.getProperty("http.proxyHost");
final String proxyPort = System.getProperty("http.proxyPort");
final String nonProxyHostsValue = System.getProperty("http.nonProxyHosts");
final ProxySelector proxySelector = new ProxySelector() {
@Override
public List<Proxy> select(URI uri) {
List<Proxy> proxyList = new ArrayList<>();
String host = uri.getHost();
if (!StringUtils.isEmpty(host)) {
if (host.startsWith(DEFAULT_HOST_IP) || host.startsWith(DEFAULT_HOST) || StringUtils
.isEmpty(nonProxyHostsValue) || StringUtils.contains(nonProxyHostsValue, host) ||
StringUtils.isEmpty(proxyHost) || StringUtils.isEmpty(proxyPort)) {
proxyList.add(Proxy.NO_PROXY);
} else {
proxyList.add(new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(proxyHost, Integer.parseInt(proxyPort))));
}
} else {
log.error("Host is null. Host could not be empty or null");
}
return proxyList;
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
throw new UnsupportedOperationException("Not supported yet.");
}
};
X509TrustManager trustAllCerts = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
};
if (isIgnoreHostnameVerification) {
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(TIMEOUT, TIMEOUT, TimeUnit.SECONDS))
.sslSocketFactory(getSimpleTrustedSSLSocketFactory(), trustAllCerts)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}).proxySelector(proxySelector).build();
return okHttpClient;
} else {
SSLSocketFactory trustedSSLSocketFactory = getTrustedSSLSocketFactory();
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(TIMEOUT, TIMEOUT, TimeUnit.SECONDS))
.sslSocketFactory(trustedSSLSocketFactory)
.proxySelector(proxySelector).build();
return okHttpClient;
}
}
private static SSLSocketFactory getSimpleTrustedSSLSocketFactory() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
return sc.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
log.error("Error while creating the SSL socket factory due to " + e.getMessage(), e);
return null;
}
}
private static SSLSocketFactory getTrustedSSLSocketFactory() {
try {
String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password");
String keyStoreLocation = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Location");
String trustStorePassword = ServerConfiguration.getInstance().getFirstProperty(
"Security.TrustStore.Password");
String trustStoreLocation = ServerConfiguration.getInstance().getFirstProperty(
"Security.TrustStore.Location");
KeyStore keyStore = loadKeyStore(keyStoreLocation, keyStorePassword, KEY_STORE_TYPE);
KeyStore trustStore = loadTrustStore(trustStoreLocation, trustStorePassword);
return initSSLConnection(keyStore, keyStorePassword, trustStore);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException
| CertificateException | IOException | UnrecoverableKeyException e) {
log.error("Error while creating the SSL socket factory due to " + e.getMessage(), e);
return null;
}
}
private static SSLSocketFactory initSSLConnection(KeyStore keyStore, String keyStorePassword, KeyStore trustStore)
throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, KeyManagementException {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
trustManagerFactory.init(trustStore);
// Create and initialize SSLContext for HTTPS communication
SSLContext sslContext = SSLContext.getInstance(SSLV3);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
SSLContext.setDefault(sslContext);
return sslContext.getSocketFactory();
}
private static KeyStore loadKeyStore(String keyStorePath, String ksPassword, String type)
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
InputStream fileInputStream = null;
try {
char[] keypassChar = ksPassword.toCharArray();
KeyStore keyStore = KeyStore.getInstance(type);
fileInputStream = new FileInputStream(keyStorePath);
keyStore.load(fileInputStream, keypassChar);
return keyStore;
} finally {
if (fileInputStream != null) {
fileInputStream.close();
}
}
}
private static KeyStore loadTrustStore(String trustStorePath, String tsPassword)
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
return loadKeyStore(trustStorePath, tsPassword, TRUST_STORE_TYPE);
}
}

@ -0,0 +1,74 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.util;
/**
* This class represents the scope data.
*/
public class ScopeUtils {
private String key;
private String name;
private String roles;
private String description;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRoles() {
return roles;
}
public void setRoles(String roles) {
this.roles = roles;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String toJSON() {
String jsonString = "{\n" +
" \"name\":\" " + key + "\",\n" +
" \"displayName\":\" " + name + "\",\n" +
" \"description\":\" " + description + " \",\n" +
" \"bindings\":[\n" +
" \" " + roles + " \"\n" +
" ]\n" +
"}";
return jsonString;
}
}

@ -122,6 +122,15 @@
<artifactId>h2-database-engine</artifactId> <artifactId>h2-database-engine</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.device.mgt.core.apimgt.extension.rest.api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
</dependencies> </dependencies>
@ -165,6 +174,9 @@
org.scannotation;version="1.0", org.scannotation;version="1.0",
org.scannotation.archiveiterator;version="1.0", org.scannotation.archiveiterator;version="1.0",
org.w3c.dom, org.w3c.dom,
io.entgra.device.mgt.core.apimgt.extension.rest.api,
io.entgra.device.mgt.core.apimgt.extension.rest.api.dto,
io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions,
org.wso2.carbon.apimgt.annotations.api, org.wso2.carbon.apimgt.annotations.api,
org.wso2.carbon.apimgt.api, org.wso2.carbon.apimgt.api,
org.wso2.carbon.apimgt.api.model, org.wso2.carbon.apimgt.api.model,
@ -187,7 +199,8 @@
org.wso2.carbon.utils;version="4.6", org.wso2.carbon.utils;version="4.6",
org.wso2.carbon.utils.multitenancy;version="4.6", org.wso2.carbon.utils.multitenancy;version="4.6",
org.wso2.carbon.apimgt.impl.definitions, org.wso2.carbon.apimgt.impl.definitions,
org.apache.commons.lang org.apache.commons.lang,
org.json
</Import-Package> </Import-Package>
<Embed-Dependency> <Embed-Dependency>
jsr311-api;scope=compile|runtime;inline=false jsr311-api;scope=compile|runtime;inline=false

@ -18,11 +18,22 @@
*/ */
package org.wso2.carbon.apimgt.webapp.publisher; package org.wso2.carbon.apimgt.webapp.publisher;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServicesImpl;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.model.Documentation; import org.wso2.carbon.apimgt.api.model.Documentation;
import org.wso2.carbon.apimgt.api.model.DocumentationType; import org.wso2.carbon.apimgt.api.model.DocumentationType;
import org.json.JSONArray;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.APIProvider; import org.wso2.carbon.apimgt.api.APIProvider;
import org.wso2.carbon.apimgt.api.FaultGatewaysException; import org.wso2.carbon.apimgt.api.FaultGatewaysException;
@ -50,7 +61,6 @@ import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.tenant.TenantSearchResult; import org.wso2.carbon.user.core.tenant.TenantSearchResult;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -357,13 +367,26 @@ public class APIPublisherServiceImpl implements APIPublisherService {
WebappPublisherConfig config = WebappPublisherConfig.getInstance(); WebappPublisherConfig config = WebappPublisherConfig.getInstance();
List<String> tenants = new ArrayList<>(Collections.singletonList(APIConstants.SUPER_TENANT_DOMAIN)); List<String> tenants = new ArrayList<>(Collections.singletonList(APIConstants.SUPER_TENANT_DOMAIN));
tenants.addAll(config.getTenants().getTenant()); tenants.addAll(config.getTenants().getTenant());
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
APIApplicationKey apiApplicationKey;
AccessTokenInfo accessTokenInfo;
try {
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials();
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
} catch (APIServicesException e) {
String errorMsg = "Error while generating application";
log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
}
try { try {
for (String tenantDomain : tenants) { for (String tenantDomain : tenants) {
PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
APIProvider apiProvider = API_MANAGER_FACTORY.getAPIProvider(MultitenantUtils.getTenantAwareUsername( PublisherRESTAPIServices publisherRESTAPIServices = new PublisherRESTAPIServicesImpl();
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration() JSONObject scopeObject = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
.getAdminUserName()));
try { try {
String fileName = String fileName =
@ -409,8 +432,18 @@ public class APIPublisherServiceImpl implements APIPublisherService {
} }
scope.setRoles(roleString); scope.setRoles(roleString);
if (apiProvider.isSharedScopeNameExists(scope.getKey(), tenantDomain)) { //Set scope id which related to the scope key
apiProvider.updateSharedScope(scope, tenantDomain); JSONArray scopeList = (JSONArray) scopeObject.get("list");
for (int i = 0; i < scopeList.length(); i++) {
JSONObject scopeObj = scopeList.getJSONObject(i);
if (scopeObj.getString("name").equals(scopeMapping[2] != null ?
StringUtils.trim(scopeMapping[2]) : StringUtils.EMPTY)) {
scope.setId(scopeObj.getString("id"));
}
}
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getKey())) {
publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope);
} else { } else {
// todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list // todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -421,18 +454,27 @@ public class APIPublisherServiceImpl implements APIPublisherService {
} }
} catch (IOException | DirectoryIteratorException ex) { } catch (IOException | DirectoryIteratorException ex) {
log.error("failed to read scopes from file.", ex); log.error("failed to read scopes from file.", ex);
} catch (APIServicesException | BadRequestException e) {
String errorMsg = "Error while calling APIs";
log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
} }
} }
} catch (UserStoreException e) { }
String msg = "Error occurred while reading tenant admin username"; catch (APIServicesException e) {
log.error(msg, e); String errorMsg = "Error while processing Publisher REST API response";
log.error(errorMsg, e);
throw new APIManagerPublisherException(e); throw new APIManagerPublisherException(e);
} catch (APIManagementException e) { } catch (BadRequestException e) {
String msg = "Error occurred while loading api provider"; String errorMsg = "Error while calling Publisher REST APIs";
log.error(msg, e); log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
} catch (UnexpectedResponseException e) {
String errorMsg = "Unexpected response from the server";
log.error(errorMsg, e);
throw new APIManagerPublisherException(e); throw new APIManagerPublisherException(e);
} finally { }finally {
PrivilegedCarbonContext.endTenantFlow(); PrivilegedCarbonContext.endTenantFlow();
} }
} }

@ -40,6 +40,7 @@
<module>org.wso2.carbon.apimgt.keymgt.extension</module> <module>org.wso2.carbon.apimgt.keymgt.extension</module>
<module>org.wso2.carbon.apimgt.keymgt.extension.api</module> <module>org.wso2.carbon.apimgt.keymgt.extension.api</module>
<module>io.entgra.device.mgt.core.apimgt.analytics.extension</module> <module>io.entgra.device.mgt.core.apimgt.analytics.extension</module>
<module>io.entgra.device.mgt.core.apimgt.extension.rest.api</module>
</modules> </modules>
<build> <build>

@ -51,6 +51,10 @@
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId> <artifactId>swagger-annotations</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.device.mgt.core.apimgt.extension.rest.api</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -143,6 +147,9 @@
<bundleDef> <bundleDef>
io.swagger:swagger-annotations:${swagger.version} io.swagger:swagger-annotations:${swagger.version}
</bundleDef> </bundleDef>
<bundleDef>
org.wso2.carbon.devicemgt:io.entgra.device.mgt.core.apimgt.extension.rest.api:${carbon.device.mgt.version}
</bundleDef>
</bundles> </bundles>
<importFeatures> <importFeatures>
<importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef> <importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef>

@ -238,6 +238,11 @@
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId> <artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<version>${carbon.device.mgt.version}</version> <version>${carbon.device.mgt.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.device.mgt.core.apimgt.extension.rest.api</artifactId>
<version>${carbon.device.mgt.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.oauth.extensions</artifactId> <artifactId>org.wso2.carbon.device.mgt.oauth.extensions</artifactId>

Loading…
Cancel
Save