Google app engine JRE Class "Black List" - google-app-engine

There is a "JRE Class White List" for the Google App Engine.
What I would really like is a "Black List" -- in other words, Java APIs that will not work on GAE. Does such a list exist? Have any developers run into problems with Java APIs on GAE?

It seems that they've taken more of a white-list approach: http://code.google.com/appengine/docs/java/jrewhitelist.html.
There is also more detail about the sandbox (what files it can access and so on) here: http://code.google.com/appengine/docs/java/runtime.html#The_Sandbox
The restrictions seem to be pretty intuitive (like restricted filesystem access, no JNI, etc).

I got a card advertising this service at Google I/O:
LTech AppEngine Compatibility Analyzer
Sounds like it might be of use to you. I have not tried it, if you do try it, please come back and comment. Thanks!

i use Servlet in my GAE project, however it is not in the whitelist even when it will work without any problem. In fact, Google mention how to use Servlet but it is not in the whitelist
import javax.servlet.http.*;
Mentioned here:
http://code.google.com/appengine/docs/java/runtime.html
but not included here:
http://code.google.com/appengine/docs/java/jrewhitelist.html
I love GAE (because the free quota) but the documentation is a mess.
I use IntelliJ and it mark as an error when the import not in the whitelist. However, it is possible to disable it.

I was looking for something when i came across this query and so thought to share the details on the black & white list of GAE(Google App Engine) so anyone getting such issue could address it properly. Details :-
appengine-agentruntime.jar has two instance variables as :-
private static Agent agent
private static Set<String> blackList
We getting blackList from agent & agent = AppEngineDevAgent.getAgent(). So if we check b) appengine-agent.jar we can find agent is Class<?> implClass = agentImplLoader.loadClass("com.google.appengine.tools.development.agent.impl.AgentImpl");
And then going to AgentImpl class i.e. c) appengine-agentimpl.jar we can
see blacklist variable getting populated at class load with the static initialization & it refers Whitelist for filtering the allowed classes.
static {
initBlackList();
}
public static Set<String> getBlackList() {
return blackList;
}
private static boolean isBlackListed(String className) {
Set<String> whiteList = WhiteList.getWhiteList();
return (!whiteList.contains(className))
&& (!className.startsWith("com.sun.xml.internal.bind."));
}
Finally can check d) appengine-tools-sdk-1.8.3.jar for list of all WhiteList classes.
Conclusion: As a hack in order to use any JRE class which do not belong to this WhiteList one need to play around either with the WhiteList or with the BlackList. A possible hack would be if you unjar the appengine-agentruntime.jar library & comment the content of reject method as
public static void reject(String className) {
/*throw new NoClassDefFoundError(className + " is a restricted class. Please see the Google " + " App Engine developer's guide for more details.");*/
}
And then again jar it and use in your project.Hope it helps.
-----------------------------------------------------------------------------
a) appengine-agentruntime.jar :- It holds the actual Runtime class which throws exception (from reject method) for classes which do not belong to above white list.
package com.google.appengine.tools.development.agent.runtime;
import com.google.appengine.tools.development.agent.AppEngineDevAgent;
import com.google.appengine.tools.development.agent.impl.Agent;
import com.google.apphosting.utils.clearcast.ClearCast;
//REMOVED OTHER IMPORTS TO KEEP IT SHORT
public class Runtime {
private static Agent agent = (Agent) ClearCast.cast(
AppEngineDevAgent.getAgent(), Agent.class);
private static Set<String> blackList = agent.getBlackList();
public static ClassLoader checkParentClassLoader(ClassLoader loader) {
ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
return (loader != null) && (loader != systemLoader) ? loader
: Runtime.class.getClassLoader();
}
public static void recordClassLoader(ClassLoader loader) {
agent.recordAppClassLoader(loader);
}
public static void reject(String className) {
throw new NoClassDefFoundError(className
+ " is a restricted class. Please see the Google "
+ " App Engine developer's guide for more details.");
}
private static boolean isBlackListed(Class klass) {
String className = klass.getName().replace('.', '/');
return blackList.contains(className);
}
// REMOVED OTHER METHODS TO KEEP IT SHORT
}
b) appengine-agent.jar :-
package com.google.appengine.tools.development.agent;
import com.google.apphosting.utils.clearcast.ClearCast;
//REMOVED OTHER IMPORTS TO KEEP IT SHORT
public class AppEngineDevAgent {
private static final String AGENT_IMPL = "com.google.appengine.tools.development.agent.impl.AgentImpl";
private static final String AGENT_IMPL_JAR = "appengine-agentimpl.jar";
private static final Logger logger = Logger.getLogger(AppEngineDevAgent.class.getName());
private static Object impl;
public static void premain(String agentArgs, Instrumentation inst) {
URL agentImplLib = findAgentImplLib();
URLClassLoader agentImplLoader = new URLClassLoader(
new URL[] { agentImplLib }) {
protected PermissionCollection getPermissions(CodeSource codesource) {
PermissionCollection perms = super.getPermissions(codesource);
perms.add(new AllPermission());
return perms;
}
};
try {
Class<?> implClass = agentImplLoader
.loadClass("com.google.appengine.tools.development.agent.impl.AgentImpl");
impl = ((AgentImplStruct) ClearCast.staticCast(implClass,
AgentImplStruct.class)).getInstance();
AgentImplStruct agentImplStruct = (AgentImplStruct) ClearCast.cast(
impl, AgentImplStruct.class);
agentImplStruct.run(inst);
} catch (Exception e) {
logger.log(
Level.SEVERE,
"Unable to load the App Engine dev agent. Security restrictions will not be completely emulated.",
e);
}
}
public static Object getAgent() {
return impl;
}
//REMOVED OTHER METHODS TO KEEP IT SHORT
}
c) appengine-agentimpl.jar :-
package com.google.appengine.tools.development.agent.impl;
import com.google.apphosting.runtime.security.WhiteList;
//REMOVED OTHER IMPORTS TO KEEP IT SHORT
public class BlackList {
private static final Logger logger = Logger.getLogger(BlackList.class.getName());
private static Set<String> blackList = new HashSet();
static {
initBlackList();
}
public static Set<String> getBlackList() {
return blackList;
}
private static boolean isBlackListed(String className) {
Set<String> whiteList = WhiteList.getWhiteList();
return (!whiteList.contains(className))
&& (!className.startsWith("com.sun.xml.internal.bind."));
}
private static void initBlackList() {
Set<File> jreJars = getCurrentJreJars();
for (File f : jreJars) {
JarFile jarFile = null;
try {
jarFile = new JarFile(f);
} catch (IOException e) {
logger.log(
Level.SEVERE,
"Unable to read a jre library while constructing the blacklist. Security restrictions may not be entirely emulated. "
+ f.getAbsolutePath());
}
continue;
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
String entryName = entry.getName();
if (entryName.endsWith(".class")) {
String className = entryName.replace('/', '.').substring(0,
entryName.length() - ".class".length());
if (isBlackListed(className)) {
blackList.add(className.replace('.', '/'));
}
}
}
}
blackList = Collections.unmodifiableSet(blackList);
}
private static Set<File> getCurrentJreJars() {
return getJreJars(System.getProperty("java.home"));
}
//REMOVED OTHER METHODS TO KEEP IT SHORT
}
d) appengine-tools-sdk-1.8.3.jar :- It has a class called WhiteList which includes all allowed JRE classes.
package com.google.apphosting.runtime.security;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class WhiteList {
private static Set<String> whiteList = new HashSet(
Arrays.asList(new String[] {
"java.beans.Transient",
"java.lang.BootstrapMethodError",
"java.lang.Character$UnicodeScript",
"java.lang.ClassValue",
"java.lang.SafeVarargs",
//Removed other classes to keep this article short
"java.net.URLClassLoader",
"java.security.SecureClassLoader",
"sun.net.spi.nameservice.NameService" }));
public static Set<String> getWhiteList() {
return whiteList;
}
}

Related

JHipster React Front End (Gateway) Application Properties

I'm building a JHipster microservice application, consisting of Microservice, Registry and Gateway (React).
In the Microservice application I can use the application.yml / ApplicatioProperties.java to add properties (such as API keys) which may change between environments (Dev, Prod etc).
My question is, can I do the same thing on the React front-end? This is a Spring application so the same application.yml and ApplicationProperties.java are in place. Does anyone have a code example of surfacing custom properties to the UI?
There's an AuthInfoResource that takes properties and makes them available at an /api/auth-info endpoint. You could so something similar to expose configuration properties to your React app.
package <%= packageName %>.web.rest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Resource to return information about OIDC properties
*/
#RestController
#RequestMapping("/api")
public class AuthInfoResource {
#Value("${spring.security.oauth2.client.provider.oidc.issuer-uri:}")
private String issuer;
#Value("${spring.security.oauth2.client.registration.oidc.client-id:}")
private String clientId;
#GetMapping("/auth-info")
public AuthInfoVM getAuthInfo() {
return new AuthInfoVM(issuer, clientId);
}
class AuthInfoVM {
private String issuer;
private String clientId;
AuthInfoVM(String issuer, String clientId) {
this.issuer = issuer;
this.clientId = clientId;
}
public String getIssuer() {
return this.issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
}
}

Trying to set up a Dapper-based Data Access Layer. ABP.Dapper documentation is confusing and incomplete

I'm trying to set up a simple DAL that will return a List of typed objects. Pretty standard data repository stuff. I downloaded all of ABP's code from GitHub, built the DLLs for Abp.Dapper and Abp.EntityFrameworkCore and started following the instructions on this page:
https://aspnetboilerplate.com/Pages/Documents/Dapper-Integration
But I can't even get past step one of this. This code doesn't compile because it doesn't know what SampleApplicationModule is. But there's no guidance in these instructions as to what that is supposed to be.
How am I supposed to use Abp's libraries? I'm lost. Can someone please let me know the minimum number of things I need to do in order to wire up my database to Abp's library and query for a List of typed objects?
Code from Abp's Dapper Integration documentation:
[DependsOn(
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpDapperModule)
)]
public class MyModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(SampleApplicationModule).GetAssembly());
}
}
if you are confused what to write for SampleApplicationModule use the below code
Module Registration
[DependsOn(
typeof(AbpEntityFrameworkModule),
typeof(AbpKernelModule),
typeof(AbpDapperModule)
)]
public class SampleApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
Usage
public class SomeDomainService : ITransientDependency
{
private readonly IDapperRepository<Animal> _animalDapperRepository;
private readonly IRepository<Animal> _animalRepository;
private readonly IDapperRepository<Person> _personDapperRepository;
private readonly IRepository<Person> _personRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public SomeDomainService(
IUnitOfWorkManager unitOfWorkManager,
IRepository<Person> personRepository,
IRepository<Animal> animalRepository,
IDapperRepository<Person> personDapperRepository,
IDapperRepository<Animal> animalDapperRepository)
{
_unitOfWorkManager = unitOfWorkManager;
_personRepository = personRepository;
_animalRepository = animalRepository;
_personDapperRepository = personDapperRepository;
_animalDapperRepository = animalDapperRepository;
}
public void DoSomeStuff()
{
using (IUnitOfWorkCompleteHandle uow = _unitOfWorkManager.Begin())
{
_personRepository.Insert(new Person("Oğuzhan"));
_personRepository.Insert(new Person("Bread"));
_animalRepository.Insert(new Animal("Bird"));
_animalRepository.Insert(new Animal("Cat"));
_unitOfWorkManager.Current.SaveChanges();
Animal animal = _animalRepository.FirstOrDefault(x => x.Name == "Bird");
Person person = _personDapperRepository.Get(1);
int personCount = _personDapperRepository.Count(x => x.Name == "Oğuzhan");
List<Animal> persons = _animalDapperRepository.GetList(x => x.Name.StartsWith("O")).ToList();
uow.Complete();
}
}
}
See the related post for AbpDapper
https://github.com/aspnetboilerplate/aspnetboilerplate/pull/1854#issuecomment-284511423
PS: Abp.Dapper integration is implemented by the community.

DNN Custom Authentication provider not displaying if default Auth provider is disabled

I followed this guide as a template to creating my custom authentication provider
DotNetNuke Tips and Tricks #12: Creating your own Authentication Provider
In that guide he creates his own authentication configuration class so that it does not share configuration with the default provider (which he built his custom provider off) which i converted to c#.
[Serializable()]
public class ScanToLoginAuthConfig
{
#region "Private Members"
private bool _Enabled = true;
private int _portalId;
private const string CACHEKEY = "Authentication.ScanToLogin.DNN";
private const string ENABLED_SETTING_KEY = "DNN_ScanToLogin_Enabled";
#endregion
#region "Constructor(s)"
protected ScanToLoginAuthConfig(int portalID)
{
_portalId = portalID;
try
{
string setting = Null.NullString;
if (PortalController.GetPortalSettingsDictionary(portalID)
.TryGetValue(ENABLED_SETTING_KEY, out setting))
{
_Enabled = bool.Parse(setting);
}
setting = Null.NullString;
}
catch
{
}
}
#endregion
#region "Public Properties"
public bool Enabled
{
get { return _Enabled; }
set { _Enabled = value; }
}
[Browsable(false)]
public int PortalId
{
get { return _portalId; }
set { _portalId = value; }
}
#endregion
#region "Public SHared Methods"
public static void ClearConfig(int portalId)
{
string key = CACHEKEY + "_" + portalId.ToString();
DataCache.RemoveCache(key);
}
public static ScanToLoginAuthConfig GetConfig(int portalId)
{
string key = CACHEKEY + "_" + portalId.ToString();
ScanToLoginAuthConfig config = (ScanToLoginAuthConfig) DataCache.GetCache(key);
if (config == null)
{
config = new ScanToLoginAuthConfig(portalId);
DataCache.SetCache(key, config);
}
return config;
}
public static void UpdateConfig(ScanToLoginAuthConfig config)
{
PortalController.UpdatePortalSetting(config.PortalId, "DNN_Enabled", config.Enabled.ToString());
ClearConfig(config.PortalId);
}
#endregion
}
This works in so far as I con toggle my authentication provider as enabled or disabled independently of the default provider, however, my provider does not load if the default provider is not enabled.
if (PortalController.GetPortalSettingsDictionary(portalID)
.TryGetValue(ENABLED_SETTING_KEY, out setting))
{
_Enabled = bool.Parse(setting);
}
When I go in to modify the settings the above code fires, but it never finds the value specified by "ENABLED_SETTING_KEY" ("DNN_ScanToLogin_Enabled"). The portal settings dictionary (for that portal ID) contains 14 items and "DNN_ScanToLogin_Enabled" is not in there. Can anyone tell me why that is, PLEASE!
EDIT
I've modified things somewhat
public static void ClearConfig(int portalId)
{
string key = CACHEKEY + "_" + portalId.ToString();
DataCache.RemoveCache(key);
}
and
public static ScanToLoginAuthConfig GetConfig(int portalId)
{
string key = CACHEKEY + "_" + portalId.ToString();
Have become
public static void UpdateConfig(ScanToLoginAuthConfig config)
{
PortalController.UpdatePortalSetting(config.PortalId, "DNN_ScanToLogin_Enabled", config.Enabled.ToString());
ClearConfig(config.PortalId);
}
and
public static ScanToLoginAuthConfig GetConfig(int portalId)
{
string key = CACHEKEY;// +"_" + portalId.ToString();
Respectively. So now the keys seem to update and set correctly (for my unspecified definition of correctly...)
However when I disable the default authentication provider and enable my authentication provider, it still does not display my provider and instead shows the default. When both default and mine are enabled, then both display, tabbed.
I also updated the following to include the key's name as it is defined at the top of the code.
public static void UpdateConfig(ScanToLoginAuthConfig config)
{
PortalController.UpdatePortalSetting(config.PortalId, "DNN_ScanToLogin_Enabled", config.Enabled.ToString());
ClearConfig(config.PortalId);
}
The first thing I would confirm is that when you installed your Authentication Provider under Host > Extensions, you configured the Enabled flag there.
BUT, to enable it for a particular Portal, you need to go to Admin > Extensions, open the Authentication Systems section, click Edit on your Provider, and Enable it there.
If you still have problems, you may issues with your settings implementation. (If you implemented settings using the AuthenticationSettingsBase).
you must change the code inside your login file and use your ScanToLoginAuthConfig class for Enabled property
public override bool Enabled
{
get
{
return ScanToLoginAuthConfig.GetConfig(PortalId).Enabled;
}
}

How do I use AIDL or talk to Android Services from codenameone?

I am building an Android POS application using codenameone. I want to use the CMSoft BT-Printer SDK from here http://www.cm-soft.com/AndroidPrinterSDK.htm. This uses an AIDL interface. How would I access it from Codenameone project?
1)Create in your project a regular interface that extends NativeInterface to communicate with the printer service.
2)
interface PrinterInterface extends NativeInterface{
public void bindService();
public void startScan();
public void stopScan();
}
3)right click on the interface and select "Generate Native Access" - this will create implementation files under the native directory in the project.
4)under the native/android dir you will get a PrinterInterfaceImpl class make sure the isSupported() method returns true and now simply implement your android code in this class.
use AndroidNativeUtil.getActivity() to gain access to your Activity.
for example:
AndroidNativeUtil.getActivity().registerReceiver(mReceiver, new IntentFilter(RECEIVER));
AndroidNativeUtil.getActivity().unregisterReceiver(mReceiver);
5)in the impl class you can bind your receiver:
final class ScannerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String data = null;
if (intent.getAction().equals(RECEIVER)) {
data = intent.getStringExtra(DATA);
}
if (data != null) {
String msg;
if (data.startsWith("S:")) {
msg = data.substring(data.indexOf(':', 2) + 1);
}
if (data.startsWith("D:")) {
msg = data.substring(data.indexOf(':', 2) + 1);
}
}
}
}
private final ScannerReceiver mReceiver = new ScannerReceiver();
private final Intent mService = new Intent(SERVICE);

Suggest Addresses in a SuggestBox in GWT/Java

I want to define a SuggestBox, which behaves like the search bar in Google Maps: When you begin to type, real addresses, starting with the typed letters, appear.
I think, that I need to use the Geocoder.getLocations(String address, LocationCallback callback) method, but I have no idea how to connect this with the oracle, which is needed by the suggest box to produce its suggestions.
Can you please give me ideas how do I connect the getLocations Method with the SuggestOracle?
I solved this by implementing a subclass of SuggestBox, which has it's own SuggestOracle. The AddressOracle deals as a Wrapper for the Google Maps Service, for which the class Geocoderin the Google Maps API for GWT offers abstractions.
So here is my solution:
First we implement the Widget for a SuggestBox with Google Maps suggestions
public class GoogleMapsSuggestBox extends SuggestBox {
public GoogleMapsSuggestBox() {
super(new AddressOracle());
}
}
Then we implement the SuggestOracle, which wraps the Geocoder async method abstractions:
class AddressOracle extends SuggestOracle {
// this instance is needed, to call the getLocations-Service
private final Geocoder geocoder;
public AddressOracle() {
geocoder = new Geocoder();
}
#Override
public void requestSuggestions(final Request request,
final Callback callback) {
// this is the string, the user has typed so far
String addressQuery = request.getQuery();
// look up for suggestions, only if at least 2 letters have been typed
if (addressQuery.length() > 2) {
geocoder.getLocations(addressQuery, new LocationCallback() {
#Override
public void onFailure(int statusCode) {
// do nothing
}
#Override
public void onSuccess(JsArray<Placemark> places) {
// create an oracle response from the places, found by the
// getLocations-Service
Collection<Suggestion> result = new LinkedList<Suggestion>();
for (int i = 0; i < places.length(); i++) {
String address = places.get(i).getAddress();
AddressSuggestion newSuggestion = new AddressSuggestion(
address);
result.add(newSuggestion);
}
Response response = new Response(result);
callback.onSuggestionsReady(request, response);
}
});
} else {
Response response = new Response(
Collections.<Suggestion> emptyList());
callback.onSuggestionsReady(request, response);
}
}
}
And this is a special class for the oracle suggestions, which just represent a String with the delivered address.
class AddressSuggestion implements SuggestOracle.Suggestion, Serializable {
private static final long serialVersionUID = 1L;
String address;
public AddressSuggestion(String address) {
this.address = address;
}
#Override
public String getDisplayString() {
return this.address;
}
#Override
public String getReplacementString() {
return this.address;
}
}
Now you can bind the new widget into your web page by writing the following line in the onModuleLoad()-method of your EntryPoint-class:
RootPanel.get("hm-map").add(new GoogleMapsSuggestBox());

Resources