I am trying to create custom Health checks in AEM 6.
I have,
1)Created a java class that extends inbuilt HealthCheck class.
2)The class looks like,
//SlingHealthCheck properties
#SlingHealthCheck(
name="Annotated Health Check Sample",
mbeanName="annotatedHC",
description="Sample Health Check defined by a java annotation",
tags={"hcTest"})
//Component and service annotations
#Component
#Service(value=HealthCheck.class)
public class HealthCheckTestClass implements HealthCheck{
#Override
public Result execute() {
Result result = new Result(Status.CRITICAL,
"Hey Something went wrong!!");
return result;
}
}
3) I have created a bundle which contains this class.
4)I have installed it in AEM from web console.
I don't know how can I configure it so that I can see the output produced by my custom health check class on AEM web console?
You can take the source code of the Apache Sling Health Check Samples bundle as an example that creates some custom health checks.
All active HealthCheck services should be visible on the OSGi console page at /system/console/healthcheck, as well as from a JMX console. See the Sling Health Checks page for more details.
See the AEM Operations Dashboard documentation for how to add such active HealthCheck services to the AEM dashboard pages - as that page says it is necessary to insert entries in the Dashboard's configuration nodes to select what's displayed on those pages.
Related
What is the difference between using #EnableResourceServer and using HttpSecurity.oauth2ResourceServer()? Why should I use one or the other?
#EnableResourceServer is an annotation from the Spring Security OAuth project that is being replaced by new OAuth features in Spring Security 5. In essence, it loads ResourceServerConfiguration, which extends WebSecurityConfigurerAdapter and configures it, creating a filter chain that gives your application resource server functionality. Check out the docs or its source code for more info.
http.oauth2ResourceServer() is in the current Spring Security 5 reference and is the way to go. It creates a BearerTokenAuthenticationFilter that intercepts requests, extracts any Bearer Tokens and attempts to authenticate. For more details, check out the source code for the filter or for the configurer that creates the filter.
I'm trying to make a Spring Boot app that will connect to Fitbit's api using spring-social. I've (half-way) implemented a ConnectionFactory and it's dependencies for Fitbit, and am trying to consume it from my app. Part of this involves starting up a ConnectController to handle the OAuth2 "dance".
When I try to hit the ConnectController through my browser at http://localhost:8080/connect or http://localhost:8080/connect/fitbit I get redirected to the whitelable error page with the message:
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
I don't really understand what I'm seeing, but when I set DEBUG level logging and use some breakpoints it looks like hitting /connect from the browser results in Spring trying to find something called connect/status and hitting /connect/fitbit result in spring trying to find something named /connect/fitbitConnect and then trying to internally make a GET request to /connect/connect/fitbitConnect.
In both cases it looks like the methods on ConnectController corresponding to /connect and /connect/{providerId} get called fine, and then Spring bombs when it goes looking for all that other stuff.
Here is the SocialConfigurer implementation I'm using which creates the ConnectController bean:
#Configuration
#EnableSocial
#PropertySource("${properties.path}/fitbot-service.properties")
public class SpringSocialConfig implements SocialConfigurer{
#Override
public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
connectionFactoryConfigurer.addConnectionFactory(new FitbitConnectionFactory(
environment.getProperty("fitbit.clientId"),
environment.getProperty("fitbit.clientSecret")
));
}
#Override
public UserIdSource getUserIdSource() {
return new SessionUserIdSource();
}
#Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new InMemoryUsersConnectionRepository(connectionFactoryLocator);
}
#Bean
public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
return new ConnectController(connectionFactoryLocator, connectionRepository);
}
}
What on earth is going on here? What am I doing wrong?
I believe this to be related to your question regarding GET vs. POST in ConnectController, so you may have already answered this for yourself. Nonetheless, let me clarify why it's looking for connect/status and connect/fitbitConnect.
Those are view names. When you do a GET for /connect, you're asking ConnectController to fetch connection status for all providers and to place it in the model, after which it will forward that model to a view whose logical name is "connect/status". Usually this is a JSP at the path "/connect/status.jsp" or maybe a Thymeleaf template at "/connect/status.html", but it can be any view following the rules of whatever Spring MVC view resolvers are in play.
Likewise, a GET request for /connect/fitbit is asking ConnectController to fetch connection status for the "fitbit" provider and to place that information in the model and forward it on to a view whose name is "/connect/fitbitConnect" (if there isn't a connection) or "/connect/fitbitConnected" (if there is a connection).
Aside from answering your question, may I also request that you tell me more about your FitBit Spring Social provider project? Is it modeled after other community-led Spring Social projects? In other words, is it a standalone extension to Spring Social that others may use? If so, tell me where it is in GitHub and I'll be happy to add it to the "Community Projects" section at http://projects.spring.io/spring-social/.
How can I authenticate with HTTP Basic, via the application server domain/secure realm, using a Session Bean published as a #WebService?
In a Web project one could use web.xml to map Roles to Groups, but I have no idea how to do it in a EJB-JAR project. I don't think it can be done with ejb-jar.xml.
Sample code, which works fine without the roles annotations:
#Stateless
#WebService(portName="RestrictedServicePort")
#DeclareRoles(value = "Administrators")
public class RestrictedServiceBean {
#RolesAllowed(value = "Administrators")
public String restrictedOperation() {
return "Secret information";
}
}
Error:
<faultstring>[EJB:010160]Security Violation: User: '<anonymous>' has insufficient permission to access EJB: type=<ejb>
Basic Credentials Header:
Authorization: Basic d2VibG9naWM6d2VsY29tZTE=
I suspect it must be done via vendor-specific configuration. I am using WebLogic 10.3.6, Java EE 5 / EJB 3.0.
Basic Auth via Policy
From the v10 docs:
A Web service can have zero or more WS-Policy files associated with
it. WS-Policy files follow the guidelines of the WS-Policy
specification. WebLogic Server uses WS-Policy files to specify the
details of the message-level security (digital signatures and
encryption) and reliable messaging capabilities of a Web service. You
can attach a WS-Policy file to a Web service endpoint, which means
that the policy assertions apply to all the operations of a Web
service endpoint. You can also attach a WS-Policy file to an
operation, which means that the policy assertions apply only to the
specific operation. In addition, you can attach a WS-Policy file to
the inbound or outbound SOAP message, or both.
It would appear you can attach a basic auth policy to your service:
<sp:TransportToken>
<wsp:Policy>
<sp:HttpBasicAuthentication/>
</wsp:Policy>
</sp:TransportToken>
You can apply this custom policy via the administrative console via the steps outlined here or you can consider referencing one of the Oracle-preconfigured policies.
Mapping Roles to Groups
The WebLogic (v12) documentation mentions the following when discussing usage of #RolesAllowed in an EJB:
You can also use the annotation to explicitly declare roles that are implicitly declared if you use the #RolesAllowed annotation on the class or a method of the class.
You create security roles in WebLogic Server using the Administration Console. For details, see "Manage Security Roles" in the Oracle WebLogic Server Administration Console Help.
The Manage Security Roles section continues on to discuss scoped roles.
You can then create a scoped role for a specific EJB that contains highly sensitive business logic. When you create a policy for the EJB, you can specify that only the scoped role can access the EJB.
More information on managing scoped roles is here.
Solved adding the role mapping as it is done in any web module, but using the proprietary weblogic-ejb-jar.xml, as follows:
<wls:security-role-assignment>
<wls:role-name>Administrators</wls:role-name>
<wls:principal-name>myweblogicgroup</wls:principal-name>
</wls:security-role-assignment>
The "myweblogicgroup" is the group created in the WebLogic security realm for which the system user used to authenticated to the web service is associated.
This link helped me.
I am developing with Spring Social and Thymeleaf from the quick start example, but I realised that it only supports one Facebook object per controller. This means the sample can't provide support for multiple users and I am guessing it has to do with the #Scope of the variable. Its runs in a Spring boot container and I wonder how I can configure this so that each session has its own Facebook object.
As you suggested, the Facebook object should be configured with request scope. If you're using the configuration support and/or Spring Boot, then it will be request scoped. Therefore, even though the controller is injected once with a Facebook instance, that instance is really a proxy that will delegate to a real FacebookTemplate instance that is created at request time for the authenticated user.
I can only assume that you're referring to the getting started guide example at http://spring.io/guides/gs/accessing-facebook/. In that case, it's using the most simple Spring Boot autoconfiguration possible for Spring Social, which includes a basic (yet not intended for production) implementation of UserIdSource which always returns "anonymous" as the user ID. Therefore, after you create the first Facebook connection, the second browser tries to find a connection for "anonymous", finds it, and gives you an authorized Facebook object.
This may seem peculiar, but it is an example app intended to get you started...and it does that. All you need to do to get a real UserIdSource is to add Spring Security to the project. That will tell Spring Social autoconfiguration to configure a UserIdSource that fetches the current user ID from the security context. This reflects a more real-world use of Spring Social, albeit obviously more involved and beyond the scope of the getting started guide.
But you can look at https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase-boot for a more complete example of Spring Social within Spring Boot.
Spring Boot autoconfigures a lot of things behind the scenes. It does autoconfigure the Facebook, LinkedIn and Twitter properties and sets up the connection factories for social providers.
However, the implementation of UserIdSource always returns “anonymous” as the user ID. Once the first Facebook connection is established the second browser will try to find a connection for “anonymous” which it finds and gives you an authorised Facebook object.
#Configuration
#EnableSocial
#ConditionalOnWebApplication
#ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder")
protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter {
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
return "anonymous";
}
};
}
}
Solution
The solution is to override the “anonymous” as the UserId for each new user/session. So for each session, we can simply return a SessionID, however, it may not be unique enough to identify users, especially if it’s being cached or stored somewhere in a connection database.
#Override
public String getUserId() {
RequestAttributes request = RequestContextHolder.currentRequestAttributes();
String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION);
if (uuid == null) {
uuid = UUID.randomUUID().toString();
request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION);
}
return uuid;
}
The solution for above problem has been talked about in detail over here
I have created a WFC RIA Service based on ASP.Net Website and adding the nuget packages for RIA service. I have also created a Service named "FactoryService" by extending DomainService class.
I have tested the service by creating a GridView with DomainDataSource pointing to the service. The service is working.
Now I want to access the service from other clients as I have enabled SOAP endpoint. But I cannot find the service's url to the svc file. I need this url to add service reference to my other projects. How do I find the service url?
I have tried the following urls and all returns 404. (namespace "WebApplication3", DomainService class "FactoryService").
- http://localhost:15066/WebApplication3-FactoryService.svc
- http://localhost:15066/services/WebApplication3-FactoryService.svc
- http://localhost:15066/ClientBin/WebApplication3-FactoryService.svc
- http://localhost:15066/FactoryService.svc
- http://localhost:15066/services/FactoryService.svc
- http://localhost:15066/ClientBin/FactoryService.svc
I have found the problem. In the DomainService class, I missed to annotate it with [EnableClientAccess()].
A domain service class must be marked with the
EnableClientAccessAttribute attribute to make the service available to
the client project. The EnableClientAccessAttribute attribute is
automatically applied to a domain service when you select the Enable
client access check box in the Add New Domain Service Class dialog
box.
As I'm using VS2013, the wizard is not available and missed to annotate it with the attribute.
Normally it has the following form
Base-Address + ClientBin + FullName of DomainService (Namespace+TypeName separated by -)
So in your case it should look like
http://localhost:15066/ClientBin/WebApplication3-FactoryService.svc
When you access this link in a Browser you will be provided a page that looks similar to this
Service
You have created a service.
To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:
svcutil.exe http://localhost:15066/ClientBin/WebApplication3-FactoryService.svc?wsdl
You can also access the service description as a single file:
http://localhost:15066/ClientBin/WebApplication3-FactoryService.svc?singleWsdl
This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:
C#
class Test
{
static void Main()
{
HelloClient client = new HelloClient();
// Use the 'client' variable to call operations on the service.
// Always close the client.
client.Close();
}
}
Visual Basic
Class Test
Shared Sub Main()
Dim client As HelloClient = New HelloClient()
' Use the 'client' variable to call operations on the service.
' Always close the client.
client.Close()
End Sub
End Class