Custom JASPIC on WebSphere error message - websphere

Though similar, the specific problem I have is not addressed in Use JASPIC auth module on WebSphere 8.5
I am getting the following error message:
SECJ8027E: The path and name of file where JASPI persistent registrations are stored must be specified using property com.ibm.websphere.jaspi.configuration.
I can set the custom property in the administration to some existing folder but I wanted to make sure that is the right approach or if there is some step I was missing.
Note I am specifically using the "embedded in application" approach rather than a server installed JASPIC module so I have something like this
#WebListener
public class JaspicInitializer implements
ServletContextListener {
#Override
public void contextInitialized(final ServletContextEvent sce) {
final Map<String, String> options = new HashMap<>();
AuthConfigFactory.getFactory()
.registerConfigProvider(AuthModuleConfigProvider.class.getName(), options, "HttpServlet", null, null);
}
}
I had the error on both WebSphere 8.5.5.11 and 9.0.0.3

From #Uux comment, I changed the way I do the registration so it no longer give the error.
#WebListener
public class JaspicInitializer implements
ServletContextListener {
private String registrationID;
#Override
public void contextDestroyed(final ServletContextEvent sce) {
AuthConfigFactory.getFactory().removeRegistration(registrationID);
}
#Override
public void contextInitialized(final ServletContextEvent sce) {
final ServletContext context = sce.getServletContext();
registrationID = AuthConfigFactory.getFactory()
.registerConfigProvider(new AuthModuleConfigProvider(), "HttpServlet",
context.getVirtualServerName() + " " + context.getContextPath(), "JEE Sample");
}
}
Also WebSphere Global Security needs to be configured with
Enable application security
Enable Java Authentication SPI (JASPI)

Related

How to upgrade spring boot admin from 1.5 to 2.0

Is there any reference guide for spring boot admin upgrade?
I have a legacy app that I need to upgrade from 1.5 to 2.0, but the entire API has changed & there is 0 info in the official reference guide. https://codecentric.github.io/spring-boot-admin/current/
For example, the main domain class now seems to be InstanceEvent, whereas it used to be 'Application'; but they hold completely different info.
Same with the class 'AbstractStatusChangeNotifier'; which now seems to use InstanceEvent & Spring webflux...
My more specific question is:
How can I get application info from spring boot admin 2.0?
I used to be able to do this; which now no longer exists in the api.
public class XXXMailNotifier extends AbstractStatusChangeNotifier {
#Override
protected void doNotify(ClientApplicationEvent event) {
try {
helper.setText(mailContentGenerator.statusChange(event), true);
} catch (IOException | MessagingException e) {
logger.error(e.getMessage());
}
}
String statusChange(ClientApplicationEvent event) throws IOException {
ImmutableMap.Builder<String, Object> content = ImmutableMap.<String, Object>builder()
.put("name", event.getApplication().getName())
.put("id", event.getApplication().getId())
.put("healthUrl", event.getApplication().getHealthUrl())
.put("managementUrl", event.getApplication().getManagementUrl())
.put("serviceUrl", event.getApplication().getServiceUrl())
.put("timestamp", DATE_TIME_FORMATTER.print(new LocalDateTime(event.getApplication().getInfo().getTimestamp())));
Well, if it might help anyone...
I looked in the code and found that I can get the info from the instance.registration object.
You can change the above in the below:
#Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
try {
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setSubject(format(subject, environment, pool, instance.getRegistration().getName(), event.getInstance().getValue()));
helper.setText(mailContentGenerator.statusChange(event, instance, getLastStatus(event.getInstance())), true);
public String statusChange(InstanceEvent event, Instance instance, String lastStatus) throws IOException {
Registration registration = instance.getRegistration();
ImmutableMap.Builder<String, Object> content = ImmutableMap.<String, Object>builder()
.put("name", registration.getName())
.put("id", instance.getId().getValue())
.put("healthUrl", registration.getHealthUrl())
.put("managementUrl", registration.getManagementUrl())
.put("serviceUrl", registration.getServiceUrl())
.put("timestamp", DATE_TIME_FORMATTER.print(new LocalDateTime(instance.getStatusTimestamp())));

How to handle Access Denied properly in Vaadin 14 LTS

I started implementing authentication and authorization for our applications written in Spring Boot (2.2.6.RELEASE) and Vaadin 14 LTS (14.6.1).
I have followed those resources:
Securing your app with Spring Security
Router Exception Handling
I have code for checking whether logged-in user has access rights to specified resources implemented in beforeEnter method. The problem is with invocation of event.rerouteToError(AccessDeniedException.class);. It tries to create an instance of the specified exception with reflection but fails because it does not contain public no-arg constructor.
private void beforeEnter(final BeforeEnterEvent event) {
if (!AuthView.class.equals(event.getNavigationTarget()) && !AuthUtils.isUserLoggedIn()) {
event.rerouteTo(AuthView.class);
}
if (!AuthUtils.isAccessGranted(event.getNavigationTarget())) {
event.rerouteToError(AccessDeniedException.class);
}
}
java.lang.IllegalArgumentException: Unable to create an instance of 'org.springframework.security.access.AccessDeniedException'. Make sure the class has a public no-arg constructor.
at com.vaadin.flow.internal.ReflectTools.createProxyInstance(ReflectTools.java:519)
at com.vaadin.flow.internal.ReflectTools.createInstance(ReflectTools.java:451)
at com.vaadin.flow.router.BeforeEvent.rerouteToError(BeforeEvent.java:720)
at com.vaadin.flow.router.BeforeEvent.rerouteToError(BeforeEvent.java:704)
What can be the best solution for that case? I am thinking about two possible solutions:
First instantiate AccessDeniedException and then pass it to overloaded method in BeforeEvent: public void rerouteToError(Exception exception, String customMessage) which should skip creating exception object by reflection
Create dedicated ErrorView and use method public void rerouteTo(Class<? extends Component> routeTargetType, RouteParameters parameters) of BeforeEvent
I decided to follow Leif Åstrand's answer. I created custom AccessDeniedException and appropriate error handler. Here is my implementation. Maybe it will be helpful for someone.
public class AccessDeniedException extends RuntimeException {
private final int code;
public AccessDeniedException() {
super("common.error.403.details");
this.code = HttpServletResponse.SC_FORBIDDEN;
}
public int getCode() {
return code;
}
}
#Tag(Tag.DIV)
#CssImport(value = "./styles/access-denied-view.css")
#CssImport(value = "./styles/access-denied-box.css", themeFor = "vaadin-details")
public class AccessDeniedExceptionHandler extends VerticalLayout implements HasErrorParameter<AccessDeniedException> {
private final Details details;
public AccessDeniedExceptionHandler() {
setWidthFull();
setHeight("100vh");
setPadding(false);
setDefaultHorizontalComponentAlignment(Alignment.CENTER);
setJustifyContentMode(JustifyContentMode.CENTER);
setClassName(ComponentConstants.ACCESS_DENIED_VIEW);
this.details = new Details();
this.details.setClassName(ComponentConstants.ACCESS_DENIED_BOX);
this.details.addThemeVariants(DetailsVariant.REVERSE, DetailsVariant.FILLED);
this.details.setOpened(true);
add(this.details);
}
#Override
public final int setErrorParameter(final BeforeEnterEvent event, final ErrorParameter<AccessDeniedException> parameter) {
final int code = parameter.getException().getCode();
this.details.setSummaryText(getTranslation("common.error.403.header", code));
this.details.setContent(new Text(getTranslation(parameter.getException().getMessage())));
return code;
}
}
I would recommend creating a custom exception type instead of reusing AccessDeniedException from Spring. In that way, you don't have to deal with the required error message at all.
As you mentioned in your first solution, you could do:
event.rerouteToError(new AccessDeniedException("Navigation target not permitted"), "");
or maybe also specify the customMessage if you want. If you see the implementation of the rerouteToError(Class) method, it just passes empty customMessage and creates the Exception - which you could do manually and that's completely acceptable. I recommend this solution.
Another solution could be to subclass AccessDeniedException and use that with reflection:
public class RouteAccessDeniedException extends AccessDeniedException {
public RouteAccessDeniedException() {
super("Navigation target not permitted");
}
}
I don't recommend this solution.

Add camel route at runtime using end points configured in property file

I own a spring application and want to add camel routes dynamically during my application startup.End points are configured in property file and are loaded at run time.
Using Java DSL, i am using for loop to create all routes,
for(int i=0;i<allEndPoints;i++)
{
DynamcRouteBuilder route = new
DynamcRouteBuilder(context,fromUri,toUri)
camelContext.addRoutes(route)
}
private class DynamcRouteBuilder extends RouteBuilder {
private final String from;
private final String to;
private MyDynamcRouteBuilder(CamelContext context, String from, String to) {
super(context);
this.from = from;
this.to = to;
}
#Override
public void configure() throws Exception {
from(from).to(to);
}
}
but getting below exception while creating first route itself
Failed to create route file_routedirect: at: >>> OnException[[class org.apache.camel.component.file.GenericFileOperationFailedException] -> [Log[Exception trapped ${exception.class}], process[Processor#0x0]]] <<< in route: Route(file_routedirect:)[[From[direct:... because of ref must be specified on: process[Processor#0x0]\n\ta
Not sure about it- what is the issue ? Can someone has any suggestion or fix for this. Thanks
Well, to create routes in an iteration it is nice to have some object that holds the different values for one route. Let's call this RouteConfiguration, a simple POJO with String fields for from, to and routeId.
We are using YAML files to configure such things because you have a real List format instead of using "flat lists" in property files (route[0].from, route[0].to).
If you use Spring you can directly transform such a "list of object configurations" into a Collection of objects using #ConfigurationProperties
When you are able to create such a Collection of value objects, you can simply iterate over it. Here is a strongly simplified example.
#Override
public void configure() {
createConfiguredRoutes();
}
void createConfiguredRoutes() {
configuration.getRoutes().forEach(this::addRouteToContext);
}
// Implement route that is added in an iteration
private void addRouteToContext(final RouteConfiguration routeConfiguration) throws Exception {
this.camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from(routeConfiguration.getFrom())
.routeId(routeConfiguration.getRouteId())
...
.to(routeConfiguration.getTo());
}
});
}

Weblogic,EJB, $Proxy99 class cast exception

Following are the modules in my project,
1. EJB module (version 3): We prepare ejb jar of this module and deploy on Weblogic11g server. It deals with database operation. It has #local, #Remote interface and #stateless classes implementing #local,#Remote interfaces.
2. Web Application : This web application takes inputs (user uploads file) from users, validates file and inserts data into database. It uses RMI.
Problem: On production (weblogic 11g server ) sometimes we observe exception saying $Proxy99 cannot be cast to "Remote interface name" (for different different classes) e.g com.xyz.fileProcessSetting.FileProcessSttgFacadeRemote.
But after some time when we again upload file, it gets uploaded successfully without any error.
Now, I do not understand how come these remote objects becomes temporarily unavailable? Never faced this issue on development/UAT environment. Also no idea how to reproduce and fix it.
Please help. Thanks in advance.
#Remote
public interface FileProcessSttgFacadeRemote {
//methods
}
#Local
public interface FileProcessSttgFacadeLocal {
//methods
}
#Stateless
public class FileProcessSttgFacade implements FileProcessSttgFacadeLocal, FileProcessSttgFacadeRemote {
//methods
}
in weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>FileProcessSttgFacade</ejb-name>
<stateless-session-descriptor>
<business-interface-jndi-name-map>
<business-remote>com.xyz.fileProcessSetting.FileProcessSttgFacadeRemote</business-remote>
<jndi-name>FileProcessSttgFacade</jndi-name>
</business-interface-jndi-name-map>
</stateless-session-descriptor>
</weblogic-enterprise-bean>
In web application also in ejb module whenever we want to call methods we use following lookup method to get remote object:
public class someclass extends EjbLocator {
public void someMethod(){
FileProcessSttgFacadeRemote fpfr = (FileProcessSttgFacadeRemote) getService("FileProcessSttgFacade");
//other code
}
}
Following is the class used for JNDI lookup:
public class EjbLocator {
public Object getService(final String jndiName) throws Exception {
try {
obj = getDefaultContext().lookup(jndiName);
} catch (final Exception exp) {
exp.printStackTrace();
}
return obj;
}
protected Context getDefaultContext() {
try {
final Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL,"weblogic");
env.put(Context.SECURITY_CREDENTIALS, "password");
env.put(Context.PROVIDER_URL, "t3://<ip>:<port>");
defaultContext = new InitialContext(env);
return defaultContext;
} catch (final NamingException nExp) {
nExp.printStackTrace();
}
return null;
}
}

Reading an OSGi config value

I've got some code like this to read a value that could be set either with a sling:OsgiConfig node or after being set in the Felix UI...
#Component(immediate = true, metatype = true, label = "Dummy Service")
public class DummyService {
#Property(label = "Dummy Service Value")
public static final String DUMMY_VALUE = "dummyValue";
private static String m_strDummyValue = "default value";
public static String getDummyValue(){
return m_strDummyValue;
}
#Activate
protected void activate(ComponentContext context) {
configure(context.getProperties());
}
#Deactivate
protected void deactivate(ComponentContext context) {
}
#Modified
protected void modified(ComponentContext componentContext) {
configure(componentContext.getProperties());
}
public void updated(Dictionary properties) throws ConfigurationException {
configure(properties);
}
private void configure(Dictionary properties) {
m_strDummyValue = OsgiUtil.toString(properties.get(DUMMY_VALUE), null);
}
}
And could be called in any consuming class as
DummyService.getDummyValue();
This is currently working in our development environment. It's also very similar to some code that another vendor wrote and is currently in production in the client environment, and seems to be working. However, I ran across this post OSGi component configurable via Apache Felix... which recommends against using a static accessor like this. Are there potential problems where getDummyValue() could return an incorrect value, or is the recommendation more about being philosophically consistent with OSGi's patterns?
Generally statics are frowned upon especially in OSGi as it involves a tight code coupling. It would be better to have DummySerivce be an interface and your class implement it with the component being a service. Then others would reference your component's service. Once injected with the service, they can call the service's methods.
You shouldn't do this for one major reason: there is no guarantee that DummyService has been configured when you access the static method - in contrast with a service reference.

Resources