Tuesday, 27 July 2010

ADF EMG at OOW'10 - a must attend event

The ADF Enterprise Methodology Group (ADF EMG) is happy to announce we've more sessions lined up at Oracle Open World 2010. As many readers will know, the ADF EMG is where ADF users get down and dirty in discussing their FMW experiences.

This year we have 3 sessions:
  • (Official on-schedule slot) S313445 - ADF Enterprise Methodology
    Group - Sunday, September 19, 14:00-15:00 | Moscone West L3, Rm 3012
  • (2 x Unconference slots) - Wednesday, September 22nd, 10:00-12:00 | Hotel Parc 55, Mason Room
Yeah, you say, but so what, who will be talking? Well how about the following presenters to tickle your fancy?
  • Frank Nimphius, well known as one of the top JDev Product Managers presenting on ADF-Security-or-Bust
  • Kito Mann, a key JSF contributor presenting on JSF2.0
  • Andrejus Baranovskis one of the ADF communities leading bloggers and presenters demoing a new ADF production system
  • Aino Andriessen of the we-only-hire-geniuses-mold from Amis on the ultimate smackdown, Automated vs Manual Builds
  • Sten Vesterli, ODTUG's 2009 best speaker, giving us some facts and myths about ADF Tuning
There's more to come, but I'm keeping Mum to save something to publish later :-)

The success of the ADF EMG is driven by you, the reader showing interest and attending. Help our volunteers to help you: We hope to see you there.

Monday, 19 July 2010

JDev – Ant build file tweak required for ojdeploy option

--

This post is out of date. Please refer the following updated post.

--

JDeveloper assists developers in generating a preconfigured Ant build script for each project within a JDeveloper application. Of particular interest in JDeveloper 11g an option is included to generate entries for ojdeploy.

The options to do this are invoked by a right click on the project at hand, New -> All Technologies -> General -> Ant -> Buidfile form Project. This will present the following dialog:


...including selecting the option "Include Packaging Tasks (uses ojdeploy)".

Within the generated build.xml script the result of this checkbox is the additional Ant target "deploy", as demonstrated in the following code sample:
















classpath="${oracle.jdeveloper.ant.library}"/>
ora:buildscript="${oracle.jdeveloper.deploy.dir}/ojdeploy-build.xml"
ora:statuslog="${oracle.jdeveloper.deploy.dir}/ojdeploy-statuslog.xml">










deprecation="${javac.deprecation}" encoding="Cp1252" source="1.6" target="1.6">































(Oops, there appears to be a bug in the SyntaxHighlighter viewer above in that it's displaying lots of close tags at line 63, just ignore them).

However there's an issue in the generated build.xml script with the ojdeploy option. The injected "deploy" target is not just dependent on the "init" and "compile" targets, but is also dependent on the output of the "copy" target below. As such modify the "deploy" target to as follows:

If you don't include this dependency, when ojdeploy generates a resulting JAR, WAR or EAR, it can fail to include all the file types listed under the "copy" target including XML files and more. As an example where this would be a problem, is if you're deploying a Common ADF Model library via the generated build.xml script with the ojdeploy option, while the resulting Java archive will include the compiled dot-class files, the XML files that constitute the Business Components would be missing in the end product making it unusable.

Verified under JDeveloper 11.1.1.2.0 build 5536 and JDeveloper 11.1.1.3.0 build 5660.

Saturday, 3 July 2010

ADF Security revisited (again again)

This is a revisit of the ADF Security features under JDeveloper 11g and subsequent deployment to WLS. There are plenty of good examples and documentation on this feature and readers are encouraged to seek those out. This post is my cut of implementing ADF Security to make sure I've all the moving pieces clearly defined in my head. As usual I thought this post may be of interest to readers.

Assumptions

Readers understand the security concepts of authentication and authorization, and readers are familiar with the WLS security "myrealm" concept.

Sample Application

What I find difficult with the JDev 11g Fusion Guide is the raw depth of information to read and assimilate around the security space. Section 29 has 80 odd pages on security which is a lot to digest. Without a doubt security is an important topic but trying to understand the full 80 pages leaves me wiped out.

To make the discussion on ADF Security easier, let's discuss an extremely simple application and then describe what we're attempting to achieve in terms of security.

Consider the following application:


... and the following page flow:


The diagram reveals the following points about our application:

1) The Splash page is a landing page for our application where new unauthenticated sessions will land as they access the application for the first time. This page will be a simple web page with no ADF Bindings. It will provide links to the other 3 pages.

2) ViewBookings, a page showing data using ADF Bindings, will be a secured page. Only authenticated users will be able to access the page and they must have the ADMIN role.

3) ViewEvents, another databound ADF page using ADF Bindings, will also be a secured page. Only authenticated users will be able to access the page, but there are no role restrictions on the page, giving any authenticated user the right to access the page.

4) ViewOrganisations, another databound ADF page using ADF Bindings, will not be secured. Therefore authenticated and non-authenticated users will be able to access the page, and implicitly via this, there are no role restrictions on the page.

(You'll note in the above points I've been careful to identify databound pages that have ADF Bindings (ie. ViewBookings) and those that don't (ie. Splash). The ADF Security mechanisms *only* work for pages that have ADF Bindings and the relating pagedef files. A page that doesn't have ADF Bindings is not secured. This implies how we treat the unbound Splash page vs the bound ViewOrganisations page is different. The mechanisms for this will become apparent further in this post.)
Best practice side note: as a general recommendation while this article demonstrates a page that is totally unsecured via the ADF Bindings mechanism, readers should give strong consideration to create PageDef files for all pages regardless if they are databound or not. This is done by selecting the Page Definitions option from the page's context menu, then allocating them the anonymous-role making them accessible to anyone as explained later in this article. Implementing this gives you a number of advantages:

a) Improved control of the public page's content, displaying different content for authenticated vs unauthenticated users
b) A consistent security implementation across all pages
c) Easier to audit the security implementation
In order to support our application as described in the points above, we'll need a number of security "parts" for our application. Following is a summary of those parts, of which we'll describe in detail next in this document

1) A login page to authenticate users
2) An application role called ADMIN
3) An application role that identifies authenticated users
4) An application role that identifies a user regardless if they're authenticated or not
5) The ability to secure the ViewBookings page for users with the ADMIN role
6) The ability to secure the ViewEvents page for users who are authenticated
7) A mechanism to create users, create roles and assign users roles

Luckily JDeveloper provides a number of features to make this easy.

We'll add one other further security requirement. Though our application will internally make use of a role named ADMIN, once deployed to our application server the role will be called ADMINISTRATOR. As such our additional requirement is:

8) Map the application role ADMIN to the enterprise role ADMINISTRATOR.

A final point before continuing, in order to keep this example simple I've steered away from the ADF Task Flow features of JDev 11g, specifically bounded task flows. In this simple example I've stuck to the default single unbounded task flow with separate pages in order to aid understanding. In reality both task flows and pages are treated in a similar fashion so what you learn here will apply to both.

Configure ADF Security

The ADF Security wizard implements a number of the security features we require. For our open application selecting the Application menu -> Secure -> Configure ADF Security option invokes the Configure ADF Security wizard. This wizard has been described in a number of other documents and examples, so I'll not talk through all it's options, but rather just show the options picked for our example.

In step 1 of 5 we pick the ADF Authentication and Authorization option:


Step 2 of 5 we'll get JDev to create a login and error login page for us, such that the user will see an in-page login page in our application to authenticate themselves:


Step 3 of 5 we'll ask JDev to blanket grant privileges to our existing pages. We'll tidy this up in a later step. Typically we wouldn't use this option but rather the "No Automatic Grants". No grants forces developers to explicitly think about each page and what privileges to define. For demonstration purposes we're showing the other option:


Step 4 of 5 we'll leave the "Redirect" option unselected. When selected this option provides the ability to have all authenticated users redirected to a standard landing page:


Step 5 of 5 tells you what changes JDev will make on your behalf to implement the features. This screen is useful as it gives you a good understanding of what configurations are required to make ADF Security work.


Once completed the most important JDeveloper screen from here for configuring security in your application is the jazn-data.xml editor. It's accessible by opening the file under Application Resources -> Descriptors -> META-INF -> jazn-data.xml, or the Application menu -> Secure -> ADF Policies. Ensure the Overview tab at the bottom of the editor is selected. On first opening the jazn-data.xml file you'll see:


As our application includes no bounded task flows, just web pages, select the Web Pages tab at the top of the editor. For our specific application it reveals:


From here you can see three of our four pages. As the Splash screen has no ADF Bindings, it does not display and therefore has no options for defining grants and priviliges. This is because as we mentioned early in the post, only databound pages are secured by ADF Security. If we alternatively select one of our databound pages we see:


In this case the ViewBookings databound page has the role "test-all" with "View" access granted to it. In a similar fashion ViewEvents and ViewOrganisations will have the same mappings. The role "test-all" and blanket assignments to each page was generated by step 3 of the Configure ADF Security wizard.

At this stage, of our initial 8 security requirements, we've implemented #1 only. Obviously the last few steps have set up a lot of internal infrastructure and configuration for us behind the scenes which assist the next sections of work.

Application Roles vs Enterprise Roles

Our application has the security requirement to create a role called ADMIN and secure the ViewBookings page with that role. In JDeveloper security "speak" this sort of role is referred to as an *Application Role*, effectively a role that the application defines and wants to enforce against certain resources, namely web pages and task flows in our ADF application. At deployment time this role is essentially private to the application.

Application Roles are distinctly different from Enterprise Roles as they have a finer level of granularity, they only apply to one application. Conversely Enterprise Roles map to user groups within an organisation and can apply across applications, though they allow the flexibility of a 1 to 1 mapping with Application Roles too.

Another way to categorize the difference between Application Roles and Enterprise Roles is where they're implemented. Application Roles are implemented in the application at hand, while Enterprise Roles are configured in our application server or higher level identity management systems such as LDAP, MS Active Directory, OID and more.

This distinction becomes important as we configure our Application Roles, as we need to define both the Application Role, the Enterprise Role, and the mappings between them. If we don't do this, when the application is deployed, and a user accesses the system with the Enterprise Role ADMINISTRATOR, the application server has no way of knowing that this maps to the application's ADMIN role.

As per the previous section the JDeveloper security wizard predefines an Application Role named "test-all" for us. From the jazn-data.xml editor this is evident on the existing grants to pages and task flows. The intention is for development and testing purposes, any user granted the test-all role has unlimited access to the application. For a production environment this role is not suitable as it is granted to all anonymous users; any user accessing the application is already a member of this role allowing unrestricted access.

To see where the Applications Roles are defined select the User and Roles tab on the bottom of the jazn-data.xml page, followed by the Application Roles node on the left hand side:. This will display the Edit JPS Identity & Policy Store dialog:


You'll note you can see the "test-all" role defined under the Application Roles node. In our case we'll add a new ADMIN role, and remove the "test-all" role as follows:


From here we want to map the Application Role to the Enterprise Role. Remember again that Enterprise Roles exist within our application server, while the Application Role is defined within our application.

We now move to creating the ADMINISTRATOR Enterprise Role under the same left node menu option:


Next we need to map the Enterprise Role to the Application Role. With the ADMINISTRATOR Enterprise Role selected, select the Assigned Roles tab on the right, followed by the plus sign and the Assign Application Role option. In the resulting Select Roles dialog select the ADMIN Application Role. The result:


Protecting our pages with Application Roles

On completing the previous steps, on returning to the ADF Policies tab followed by the Web Pages tab, we'll note that because we removed the test-all role, none of the databound pages have roles assigned to them (identified by the fact they no longer have arrows to the right of them):


To allow users with the ADMIN Application Role to access the ViewBookings page, we simply select the page, the plus button allows us to pick the ADMIN role from the appropriate dialog, and finally we select the View option on the right hand side:


The 4 other privileges, Customize, Edit, Grant and Personalize are relevant to MDS and not applicable to this post. As such the remaining View privilege tells us ADF Security via the jazn-data.xml file is at it's most basic determining if a user can access the page or not. It's not concerned with any other privileges.

Testing

This presents a good time to test our solution. Before we can test our solution we need to create a user with the appropriate roles.

There's two ways we can do this. In WLS we can create the user and Enterprise Role ADMINISTRATOR, and allocate the role to the user.

For development purposes JDeveloper presents a "cheats" way of doing this. We return to the jazn-data.xml editor and select the Users and Roles tab followed by selecting the Users node on the left. From here we can define users and their passwords (aka Credentials) and then via the Assigned Roles section we can select the ADMINISTRATOR Enterprise Role:


(Note if you have trouble defining the user's password, where JDeveloper shows a red box around the password field, this is because passwords must be a minimum length of 8 characters)

For testing purposes we'll also create a 2nd user who isn't allocated any roles at all:


Normally we wouldn't be creating such users in our JDev application, they'd be created in our WLS server or a connected LDAP server or similar. JDeveloper allows us to get away with this because of the following option. If you select the Applications menu -> Deployment node, you'll see JDev has autoconfigured an EAR deployment descriptor for you, with a number of options below:


In particular the Users and Groups check box means that JDev will attempt to deploy the Enterprise Role ADMINISTRATOR and the two users we created CMUIR and JDOE to the server when the application is deployed.

On running our app for the first time we can happily land on the Splash page.


(ok, ok, it's a very uninspiring application. If you want whiz bang go read a post on DVT controls)

Clicking the View Bookings link, the user is interrogated for their credentials via the logon screen:


Of note in the JDev log window you'll see the authorisation challenge as follows:

[JpsAuth] Check Permission
PolicyContext: [ADFSecurityDemo#V2.0]
Resource/Target: [view.pageDefs.ViewBookingsPageDef]
Action: [view]
Permission Class: [oracle.adf.share.security.authorization.RegionPermission]
Result: [FAILED]
For more information on this failure, please set -Djps.auth.debug.enable=true

Presumably this is the mechanism that tells the ADF application to show the login page.

If we log in as CMUIR allocated with the ADMIN role we see the View Bookings page in all it's glory. Alternatively if we log in as JDOE without the ADMIN role we see the rather flattering exception:

oracle.adf.controller.ControllerException: ADFC-06000: The ADF Controller caught exception {0} while performing control flow routing. See the stack trace for details.
at oracle.adfinternal.controller.util.Utils.createAndLogControllerException(Utils.java:203)
at oracle.adfinternal.controller.state.SuspendedNavigationState.resume(SuspendedNavigationState.java:54)
at oracle.adfinternal.controller.application.LoginSuccessHandler.resumeNavigation(LoginSuccessHandler.java:117)
at oracle.adfinternal.controller.application.LoginSuccessHandler.doCreateView(LoginSuccessHandler.java:61)
at oracle.adfinternal.controller.application.BaseRequestHandlerImpl.createView(BaseRequestHandlerImpl.java:57)
-snip-
oracle.adf.controller.security.AuthorizationException: ADFC-0619: Authorization check failed: '/ViewBookings.jspx' 'VIEW'.
at oracle.adf.controller.internal.security.AuthorizationEnforcer.handleFailure(AuthorizationEnforcer.java:147)
at oracle.adf.controller.internal.security.AuthorizationEnforcer.checkPermission(AuthorizationEnforcer.java:126)
at oracle.adf.controller.internal.security.AuthorizationEnforcer.checkRead(AuthorizationEnforcer.java:363)
at oracle.adfinternal.controller.activity.ViewActivityLogic.execute(ViewActivityLogic.java:77)
at oracle.adfinternal.controller.engine.ControlFlowEngine.doRouting(ControlFlowEngine.java:876)
-snip-
This is also recorded in the WLS logs. While it doesn't look nice, effectively ADF Security is telling JDOE to get nicked because he doesn't have the ADMIN role. If you wish to handle this in a more graceful way you can make use of the ADF controller's declarative exception handler to route the user to a "friendly" denied-access page, or alternatively we wouldn't have given the user the option to navigate to this page in the first place. Of course this article shows the above for learning purposes.

Of note if we were to log in as CMUIR or JDOE and access either the ViewEvents or ViewOrganisations pages we'll also see the same error. This occurs because we haven't allocated any privileges to these pages yet.

We've now satisfied our original security requirements #1, #2, #5, #7 and #8.

Allowing any authenticated user access

Our next requirements #3 and #6 are to secure the ViewEvents page, allowing only authenticated users to access this page, regardless of which roles they've been allocated.

On returning to the jazn-data.xml editor, selecting the ViewEvents page and then the plus button, you'll note in the dialog that shows there are 2 other predefined roles besides our ADMIN role, namely "anonymous-role" and "authenticated-role":


Quoting straight from the JDev online help:

"The anonymous-role is a role you can use when you want to grant access privileges to unauthenticated users. All users, including unauthenticated users, for example, those not required to log on to the application, are automatically considered by Oracle Platform Security to be a member of the anonymous-role. The authenticated-role is a generic role that you can use to allow authenticated users to access the databound web pages of your application. The authenticated-role requires the user to be successfully logged on."

As such if we allocate the authenticated-role to the ViewEvents page, and....


Alllowing unauthenticated users access

...for our requirement #4, we allocate the anonymous-role to the ViewOrganisations page:


....we satisfy the remaining requirements.

Testing

Now on testing our application, landing on the Splash screen we discover:

a) cmuir user can access all 4 pages
b) jdoe can access Splash, ViewEvents and ViewOrganisations, but not ViewBookings
c) an unauthenticated user can access Splash and ViewOrganisations, but not ViewBookings or ViewEvents

Troubleshooting

Some developers may find regardless of the above post, they may still encounter ADFC-06000/ADFC-0619 errors when accessing a page with a user who has the appropriate application role. A common reason you can still get this error is you've forgotten to map the Enterprise Role to the Application Role as described in the last part of the Application Roles vs Enterprise Roles section.

Further to this it's possible to see further debug output out of the ADF security engine (implemented by something called OPSS) by following this post by Duncan Mills.

Credit

My thanks must go to Frank Nimphius for reviewing this article oh-so-long-ago back in September 2009. Apparently having a 2nd daughter has somewhat delayed publication of some of my articles. God knows how people with 3 kids get anything done.

Thursday, 1 July 2010

Set the ADF whale free! Um no, why ADF should be a "cost option" to truly save the whale

I had a chance at this year's ODTUG conference to throw an idea out there. It goes against the grain, but sometimes opposite ideas stir useful discussion.

From the ADF EMG, the OTN forums, user group conferences, and more, we often hear the statement "set the ADF whale free!" (okay, "whale" is my word, but it has a certain ring to it) The going idea is if the whole ADF stack was free, or at least there was a free "nobbled" version, it would assist the adoption of ADF because developers like free stuff and they would naturally start using it.

Fair enough, it's a good idea, free is good, at least, it's good for the consumer. No argument there on my part.

By the way, for the uninitiated, the Oracle JDeveloper IDE is free to use, while ADF the major JEE web framework supplied with JDeveloper, is (to coin the right phrase) "a no cost option" on OAS and the contemporary WLS platform. "No cost option" means you don't pay for it directly, instead you pay for it through your OAS/WLS license as a "bonus". This is something I've discussed before.

Anyway, what developers want is for ADF to be free. Agreed?

Yet, would that necessarily help the uptake of ADF?

Huh, what? We're talking about ADF being free aren't we?

Um, well, I've tricked you, you already agree with me. Look back and see what I said. To quote with my emphasis: "if the whole ADF stack was free ..... it would ASSIST THE ADOPTION of ADF".

Okay, so we're also talking about ADF adoption as well, not just about ADF being free.

So for sake of discussion, let's take this idea of "ADF adoption" on board, and let's put "make ADF free" aside for the moment. Further to this, let's discuss something I've noticed waaaaaaaaaay in the outback of Australia, far away from Oracle HQ, that may change your mind on how to drive ADF adoption.

When you work away from OTN, the forums, the user group conferences, and you start working with enterprise customers using Oracle, the customers' main interface to Oracle and technology is their management talking to Oracle salesmen in your local region (Australia being my case), the salesmen trying to push Oracle technologies. (And I should also comment that most of us know the emphasis Oracle puts on salesmen via Larry's recent announcements of a huge Sun hiring spree for new salesmen, while sacking technical staff)

So the 2 parts of the equation on Oracle software adoption are "management", and "Oracle salesmen".

As we know management has a large influence on the adoption of a specific technology into most enterprises. We can't discount developers in this equation, but managers are surely the biggest part.

And as we know an Oracle salesmen's job is to "sell" Oracle technology to management though all sorts of techniques. And what's the driver for Oracle sales to "SELL" something? Kind of obvious isn't it. Something that has monetary value. And we also know that most salesmen don't work for wages alone, they work for wages and commission. (okay, that's a lot of "ands", we're running with logical A-B-C progression here)

So maybe at this point our question on ADF adoption has changed. Will setting ADF free give any reason for an Oracle salesmen to "->SELL<-" ADF?

A: The going answer has to be no. They have no real reason as it's a "no cost option" on OAS/WLS that makes them no direct commission.

And before you scoff at this idea, can you really? Think about most salesmen you know. What's priority number 1 to them? Making money for themselves or doing the best for their products/employer/customers/whatever.

You know the answer to that.

So, how do we get Oracle salesmen to sell ADF.

You know it.

Oracle needs to charge directly for ADF (or maybe potentially the IDE as part and parcel).

Then, and only then will the salesmen start making commission.

And then they'll start pushing ADF along with that $1mill Exadata server to customers.

And then management will wonder what they've bought, and start pushing ADF onto their developers.

And then, well, you get it.


Free is good.


Money is better.


Maybe ADF should be a "cost option".