JAAS: How to load config file? - java

I'm trying to run the JAAS code sample.
lc = new LoginContext("JaasSample", new TextCallbackHandler());
To register the configuration file I try the command:
java -Djava.security.auth.login.config=jaas.config JaasAcn
And gets the error:
Error: Could not find or load main class .security.auth.login.config=jaas.config
Caused by: java.lang.ClassNotFoundException: /security/auth/login/config=jaas/config

Firstly write javax instead of java, so:
java -Djavax.security.auth.login.config=jaas.config JaasAcn
And second, consider to config it programmicly:
Inherit the javax.security.auth.login.Configuration class.
Override the function AppConfigurationEntry[] getAppConfigurationEntry(String name). In this func you can return an AppConfigurationEntry object that represent a row in config file.
new AppConfigurationEntry(NTLoginModule.class.getName(),
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, new HashMap<>())
With name parameter you can responde for the name parameter in LoginContext constructor.
Create object from your Configuration class and put him in Configuration:
MyConfiguration config = new MyConfiguration();
Configuration.setConfiguration(config);
The shortened code can look like this:
Configuration config = new Configuration() {
#Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return new AppConfigurationEntry[]{
new AppConfigurationEntry(NTLoginModule.class.getName(),
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
new HashMap<>())
};
}
};
Configuration.setConfiguration(config);

Clearly there is a typo in the command line: a space after -Djava, so the .security.auth.login.config=jaas.config part is taken as the class name (and hence also mangled accordingly).

Related

Can't access to sun.security.pkcs11.SunPKCS11 in Java 11

I try to write Java code to get the private key in my USB token
and I get the following error:
return new SunPKCS11(tmpConfigFile.getAbsolutePath());
'SunPKCS11(sun.security.pkcs11.Config)' is not public in 'sun.security.pkcs11.SunPKCS11'. Cannot be accessed from outside package
Thank a lot !
It's been a while when this question has been asked, but for all with the same question, this might still help.
Java 11 changed the way PKCS#11-keystores are accessed as described in the updated PKCS#11 Reference Guide for Java 11. Instead of initializing via constructor you're supposed to get the Provider via Security.getProvider and then call configure. An example can be found in the reference guide:
String configName = "/opt/bar/cfg/pkcs11.cfg";
Provider p = Security.getProvider("SunPKCS11");
p = p.configure(configName);
There is multiple ways :
Create a new class that is in sun.security.pkcs11 package, and create the object for you, like that:
package sun.security.pkcs11;
public class MyClass {
public static SunPKCS11 createPKCS(Config config) {
return new SunPKCS11(config);
}
}
Use reflection
public SunPKCS11 create(Config config) {
Constructor<?> pkcsCons = SunPKCS11.class.getConstructor(Config.class);
pkcs.setAccessible(true);
return pkcsCons.newInstance(config);
}
Check this documentation more speficially the 2.2 paragraph

How to redefine loaded classes from compiled classfiles

I'm trying to redefine an existing class (called Module) in my code with new versions during runtime. The new versions come in the form of compiled classfiles that are saved in some directory. Is there a way for me to do this with ByteBuddy?
I have tried to use the ByteArrayClassLoader to define a class from the classfile. The defined class seems to have the updated methods. I've checked this by going through the methods of the defined class and invoking them (i.e the process method which returns some String). However, when I try to use ByteBuddy.redefine(...), I get the error "Could not locate class file for some.package.Module" I tried passing in the ClassFileLocator I used to find the class file for the new version but I still get this error.
public void redefine() throws Exception {
String path = System.getProperty("user.dir")+"/someDir";
Map<String, byte[]> map = new HashMap<>();
ClassFileLocator cfl = new ForFolder(new File(path));
byte[] clazzBytes = cfl.locate("Module").resolve();
map.put(clazz.getName(), clazzBytes);
ByteArrayClassLoader bac = new ByteArrayClassLoader(ClassLoadingStrategy.BOOTSTRAP_LOADER, false, map);
Class<?> replacementClass = bac.defineClass(clazz.getName(), clazzBytes);
for (Method m : replacementClass.getMethods()) {
if (m.getName().equals("process")) {
System.out.println((String) m.invoke(replacementClass.newInstance(), "invoked from new instance"));
}
}
AgentBuilder agentBuilder = new AgentBuilder.Default()
.with(new Listener.Filtering(
new StringMatcher("bytebuddy_instrumentation.Module", Mode.CONTAINS),
Listener.StreamWriting.toSystemOut()
))
.with(RedefinitionStrategy.REDEFINITION)
.with(Default.REDEFINE)
.disableClassFormatChanges()
.type(ElementMatchers.is(clazz))
.transform((builder, typeDescription, classLoader, module) ->
new ByteBuddy()
.redefine(replacementClass, cfl)
.name(clazz.getName()));
this.resetter = agentBuilder.installOnByteBuddyAgent();
}
The redefinition fails with the current code due to java.lang.IllegalStateException: Could not locate class file for some.package.Module
If you simply want to replace another class with another byte code representation, why would you want to use Byte Buddy?
You can replace a class with the Instrumentation API by using redefineClass where you can directly pass the replacement.
The error probably stems from your use of a REDEFINE strategy where Byte Buddy needs to locate the class files of all classes. It would probably be better to use RETRANSFORM. However, it is impossible to tell for sure without a stack trace.

How to access Karate config parameters in JUnit tests?

Is there a way to access the config parameters from karate-config.js within JUnit tests?
Example:
karate-config.js
function fn() {
var env = karate.env; // get java system property 'karate.env'
karate.log('karate.env system property was:', env);
if (!env) {
env = 'dev'; // a custom 'intelligent' default
}
var config = { // base config JSON
appId: 'my.app.id',
appSecret: 'my.secret',
someUrlBase: 'https://some-host.com/v1/auth/',
anotherUrlBase: 'https://another-host.com/v1/'
};
if (env == 'stage') {
// over-ride only those that need to be
config.someUrlBase = 'https://stage-host/v1/auth';
} else if (env == 'e2e') {
config.someUrlBase = 'https://e2e-host/v1/auth';
}
// don't waste time waiting for a connection or if servers don't respond within 5 seconds
karate.configure('connectTimeout', 5000);
karate.configure('readTimeout', 5000);
return config;
}
MyTest.java
public class MyTest {
#Test
public void test() {
// How to access e.g. config.appId?
}
}
But why !?
There are multiple ways, but first - maybe you are over-engineering things and note that it is possible to read a *.properties file in Karate: properties.feature
You can also create a feature file with a single, empty Scenario - and call it from the Java API: https://github.com/intuit/karate#java-api
Map<String, Object> result = Runner.runFeature('classpath:foo.feature', null, true);
Which will give you the values of config in the returned Map.
if you need to call external javascript functions from java code I suggest you take a look at this

How to load a properties file in java without calling laod method separately

How to load a properties file in java without calling laod method separately
i want to load the file while instantiation of the properties object itself.
like i have pasted below but i am not able to succeed in it.
class test{
Properties configFile = new Properties(load(new FileInputStream("config.properties"));
}
Just create a separate method to do that - potentially in a helper class you can use elsewhere:
public class PropertiesHelper {
public static Properties loadFromFile(String file) throws IOException {
Properties properties = new Properties();
FileInputStream stream = new FileInputStream(file);
try {
properties.load(stream);
} finally {
stream.close();
}
return properties;
}
}
Note that due to the possibility of an IOException, you'll still need to be careful where you call this from. If you want to use it in an instance initializer, you'll need to declare that all of your constructors can throw IOException.
Something along the lines of this:
class Test {
Properties configFile = new Properties() {{ load(new FileInputStream("config.properties")); }};
}
You are actually sub classing Properties here and using its initialization section.
load(..) might throw an Exception if so you would need to add a try { ... } catch () {}

How to implement overriding properties policy with rocoto ?

I would like to implement properties policy in my application : i want to define default properties inside my application, and in case of, i want to keep possibility to overriding this default parameters by a config file outside of the war file.
So i define a ConfigModule.java:
public class ConfigModule extends AbstractModule {
private static final Logger LOG = LoggerFactory.getLogger(BatchConfigModule.class);
#Override
protected void configure() {
LOG.info("Start rocoto configuration");
Module rocotoModule = Rocoto.expandVariables(new ConfigurationModule() {
#Override
protected void bindConfigurations() {
// default config
LOG.debug("Default config");
bindProperties(Config.DEFAULT_CONFIG);
LOG.debug("before config.properties");
// // For overriding default config
File propertiesFile = new File(Resources.getResource("config.properties")
.getFile());
if (propertiesFile.exists()) {
LOG.info("config.properties was found in classpath: ["
+ propertiesFile.getAbsolutePath() + "]");
bindProperties(propertiesFile);
} else {
LOG.info("config.properties was not found in classpath");
}
}
});
install(rocotoModule);
}
}
Config.DEFAULT_CONFIG extends java.util.Properties and define default properties, each parameters in DEFAULT_CONFIG is like this =>
DEFAULT_CONFIG.setProperty("testModeInt", "${testMode|false}");
And i inject in my code property with #Named("testModeInt").
My problem is, if my config.properties is not present in classpath, i have an error :
Caused by: java.lang.IllegalStateException: Re-entry not allowed
at com.google.inject.internal.util.$Preconditions.checkState(Preconditions.java:142)
at org.nnsoft.guice.rocoto.configuration.ConfigurationModule.configure(ConfigurationModule.java:63)
at com.google.inject.AbstractModule.configure(AbstractModule.java:59)
at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:223)
at com.google.inject.spi.Elements.getElements(Elements.java:101)
at com.google.inject.spi.Elements.getElements(Elements.java:92)
at com.google.inject.util.Modules$RealOverriddenModuleBuilder$1.configure(Modules.java:152)
at com.google.inject.AbstractModule.configure(AbstractModule.java:59)
at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:223)
at com.google.inject.AbstractModule.install(AbstractModule.java:118)
at net.antoine.ConfigModule.configure(ConfigModule.java:51)
Which i just don't understand, where is this problem come from, or maybe this implementation is not good, another idea ?
You can try OWNER API: it supports 3 levels of properties overriding, and it also provides mapping between a Java object and properties files and other neat features.
The first overriding capability is the specification of the default value on the mapping interface:
public interface ServerConfig extends Config {
#DefaultValue("42")
int maxThreads();
}
ServerConfig gets mapped by default to ServerConfig.properties in the same package. If the property "maxThreads" is not specified, then 42 is used as default (the properties files overrides the DefaultValue).
The second overriding capability is the possibility to specify multiple properties file locations for the class, so the first resource found is used. This way you define an internal properties in your jar, and allow the user to specify an overriding properties file in his home directory or in /etc/myapp, or everywhere else you prefer:
#Sources({ "file:~/.myapp.config",
"file:/etc/myapp.config",
"classpath:foo/bar/baz.properties" })
public interface ServerConfig extends Config {
#Key("server.http.port")
int port();
#Key("server.host.name")
String hostname();
#Key("server.max.threads");
#DefaultValue("42")
int maxThreads();
}
The third overriding capability is to specify that you want all of the above file being considered but you want the override to happen to a property level, so that if all the above
properties file are available, when you ask for the property maxThreads(), this will be searched first in file:~/.myapp.config - if not found - then in file:/etc/myapp.config and then in classpath:foo/bar/baz.properties, and as last resort the #DefaultValue("42") applies, then you specify to the library that it has to produce a merge of all the properties resources (and consider them all)
#LoadPolicy(LoadType.MERGE)
#Sources({ "file:~/.myapp.config",
"file:/etc/myapp.config",
"classpath:foo/bar/baz.properties" })
public interface ServerConfig extends Config {
// same content as above.
}

Categories