Showing posts with label oes. Show all posts
Showing posts with label oes. Show all posts

Friday, May 23, 2014

OAG/OES Integration for Web API Security: skin and guts

Introduction


When it comes to defining a strategy for web API security, OAG (Oracle API Gateway) and OES (Oracle Entitlements Server) together present a very interesting choice and are a very powerful combination indeed.

In this post we're going to take a look at what each component brings in (the skin) and then get our hands on actually describing the integration in detail (the guts).

OAG is designed to inspect and act on various types of messages that are delivered to it or just pass through it. It's usually positioned to be deployed on the DMZ (the De-Militarized Zone) within corporate networks. As such, it can block malicious traffic, authenticate users with a variety of protocols, integrate with anti-virus products, perform message throttling, thus delivering only the good stuff to your intranet servers and also off-loading them, decisively contributing to achieve some IT operational SLAs. More than that, OAG can switch protocols and transform messages. For instance, an organization may have SOAP-based web services and want to expose them as REST without any re-writing. Or implement SAML federation without touching origin systems. Or talk Kerberos or OAuth with clients and speak SAML with back-end servers. Or use it as an FTP server so that incoming files are immediately sent to a processing pipeline. The possibilities are numerous. Having mentioned these few features and examples, it's not unreasonable to think deploying OAG inside intranets. And that's not unusual, actually. It is a nice bridge with obvious benefits.

OES is designed to provide fine-grained authorization with externalized policies to client applications. It takes the coding of access decisions away from developers. Besides the obvious security pro, it shortens the change cycle, when a new security policy needs to be deployed. You simply avoid going through all the phases required for re-deploying your application just because of that change. It's true the new policy needs testing, but that's nowhere near when compared to what it takes to re-deploy a new application version. The time to market is drastically reduced. Now to the fine-grained part. OES can take a bunch of aspects in consideration when authorizing: the user identity, user roles, user attributes, context information about the request being made (like originating IP address), factors external to the request (like time of day, day of week, etc) and, of course, request data. Those combined makes it a very powerful authorization engine. It's not coincidence that OES is the component behind OAM's (Oracle Access Manager) authorization engine.

While OAG itself brings in authorization capabilities, in this field OES offers a much richer model. And if the organization already employs OES elsewhere, integrating it with OAG makes a lot of sense, because we end up with a single and consistent approach for authorization across applications.

Friday, July 22, 2011

High Availability OES 11g Admin

Setting up High Availability (HA) in OES means a lot of things: Redundancy at the data layer (typically database), the admin layer (WebLogic or WebSphere), and depending on the policy model, the decision layer (PDP). HA for the admin is probably the least important of the three, as the PAP isn't part of the runtime typically, but I wanted to address the admin (PAP) layer for the time as it is fresh on my mind and there is a missing parameter in the docs that makes this hard.

The idea is that you would have two WebLogic domains using the same policy store, so that if one domain went down, you could still make policy edits, enroll, distribute changes, etc. As part of the initial post-install configuration for your first OES admin (let's call it instance1), you have to associate the underlying security services (OPSS) with a datastore. Let's assume you want to use database. http://download.oracle.com/docs/cd/E21764_01/install.1111/e12002/oes.htm#CIHCCDCB describes how to do this. The command is:

configureOESAdminServer(servertype="DB_ORACLE");


Table 19-2 shows that you can specify a domain here, but will default to 'oes_domain'. What I've found is that it doesn't really have to match the actual WebLogic domain for this to work, but it is important in the HA configuration. Now say we configure instance2 on the same physical server, say on port 8001. We need to associate this domain as well, but we need to have it join the same policy store as the first domain. The way you do this is to WLST into the second domain (t3://instance2:8001), and run the following:

configureOESAdminServer(servertype="DB_ORACLE", domain=oes_domain, join="true")


Here I explicitly call out the first domain that I am joining, NOT the WebLogic domain name that I am running in. Because I didn't specify domain in instnace1, it default to oes_domain, and so that is what I want to join. Once you restart instance2, then you should be making updates to the same policy store from both OES servers. The join option isn't mentioned on this install page. I'm sure they'll include it once the Enterprise Deployment Guide for 11.1.1.5 is out.

Tuesday, June 14, 2011

Oracle Entitlements Server 11g launch party!

OK, well maybe party isn't the right word, but there is a launch event:

We will be offering a live launch webcast featuring Roger Wigenstam from Oracle and Swapnil Mehta from SENA systems on Jul 14 at 10 am PT. The webcast is titled “Introducing Oracle Entitlements Server 11g” . During this webcast we will cover what’s new in Oracle Entitlements Server 11g in addition to recommendations for planning a real world deployment for externalizing authorization from apps.
Roger is a Product Manager at Oracle in charge of OES, OPSS, OWSM and OEG (technically he's a Senior Director of Product Management).

Swapnil is the Director of SENA Systems' Global Access Management Practice. I've worked with him since I went to work at BEA as part of the sales team for OES' predecessor product Aqualogic Entitlements Server.

The product has been improved and enhanced quite dramatically in the 11g release and there's plenty to talk about. This event is basically two really smart guys talking about what's in OES 11g and why we're all pretty excited about the release.

More information on the event is available on the event page.

Those of you that can't make it to the online event can rest assured that I'll be blogging a whole lot more about OES 11g here for both new and existing users of OES!

Friday, January 7, 2011

Risky Business

Incorporating risk detection and mitigation capabilities into apps is becoming all the rage. There are plenty of real-life examples of cases where prevention of cyber-security threats and fraudsters might have kept governments and companies out of the news, and with more money in their accounts. These are just the events that we know about. There are probably many more that have been kept on the down-low or haven’t been detected yet. Oracle’s Adaptive Access Manager provides a risk engine that can help you model, detect and mitigate those threats.

The quickest way to start using the Adaptive Risk Manager (henceforth ARM), is to call the Strong Authenticator. This is done by browsing to http://<oaam_host>:14300/oaam_server. Login with any username and password ‘test’ and you should be ‘authenticated’. I put authenticated in quotes because OAAM doesn’t go against any directory service out of the box. At this point you should be able to browse to the ARM console and see your session information. Browse to http://<oaam_host>:14200/oaam_admin and doubleclick ‘Sessions’. You should see an entry in the table for the user you just authenticated as.

There are 3rd party tools like ARMAutomator that provide extensive testing on ARM testing, but for onesie-twosie testing and demoing, you can use this native integration JSP I put together. To set up native in your own Java EE web app, do the following:

Copy the following jars to your client-side web app WEB-INF/lib:

- oaam_core.jar

- oaam_native_wrapper.jar (had to extract it from the native lib war)

- oaam_uio.jar

Copy bharosa_properties folder from /Oracle_IDM1/oaam/cli to /WEB-INF/classes

Update the JDBC URL in oaam_core.properties in bharosa_properties folder to your environment.

Include the following bharosa_server.properties in your WEB-INF/classes folder and update the SOAP URL.

vcrypt.tracker.soap.url=http://<oaam_host>:14300/oaam_server/services

bharosa.config.impl.classname=com.bharosa.common.util.BharosaConfigPropsImpl

bharosa.config.load.impl.classname=com.bharosa.common.util.BharosaConfigLoadPropsImpl

vcrypt.tracker.soap.useSOAPServer=true

vcrypt.soap.auth=false

I cheated a bit and disabled the basic auth constraint on the server side. If you have a 10g setup with a soap keystore setup, you can leave this in place, but if you want disable it, perform the following steps on the OAAM server:

- cd /Oracle_IDM1/oaam/oaam_server/ear

- back oaam_server.ear

- jar xvf oaam_server.ear oaam_server.war

- jar xvf oaam_server.war WEB-INF/web.xml

- Edit web.xml and remove <security-constraint>...</security-constraint>

- jar uvf oaam_server.war WEB-INF

- jar uvf oaam_server.ear oaam_server.war

- Redeploy oaam_server.ear

If you haven’t upgraded to OAAM BP01 (p10022410), I would do that upgrade before removing this constraint. If done correctly, you should be about to browse the following URL without being prompted by Basic Auth prompt:

http://<oaam_host>:14300/oaam_server/services/VCryptRulesEngineWS?wsdl

A very quick ‘n dirty way to see how OAAM geo-spatial capability can work is to load the test data included in the tool. Quova from what I’ve heard is the top-tier service for IP Geo-location. Here’s a perl script to convert those numbers to IP address format:

sub numToStr {

my ($ipnum) = @_;

my $z = $ipnum % 256;

$ipnum >>= 8;

my $y = $ipnum % 256;

$ipnum >>= 8;

my $x = $ipnum % 256;

$ipnum >>= 8;

my $w = $ipnum % 256;

print "$w.$x.$y.$z";

return "$w.$x.$y.$z";

}

print "IP Address is ";

&numToStr($ARGV[0]);

Assuming you’ve imported the IP GeoLocation test data, you can take a value from /oaam/cli/test_data/test_MaxMindBlocks.csv and pass it into the tool.

perl convertLongToIP.pl 209868800

Credit to Maxmind for that little tool.

Here is the JSP I use to call ARM for post-authentication results:


<%@ page import="com.bharosa.client.BharosaHelper"%>

<%@ page import="com.bharosa.client.BharosaUtil" %>

<%@ page import="com.bharosa.client.BharosaSession"%>

<%@ page import="com.bharosa.vcrypt.common.util.VCryptServletUtil" %>

<%@ page import="com.bharosa.client.enums.BharosaEnumAction"%>

<%@ page import="com.bharosa.vcrypt.tracker.util.CookieSet" %>

<%@ page import="com.bharosa.client.enums.BharosaEnumAuthStatus" %>

<%@ page import="com.bharosa.common.util.StringUtil" %>

<%@ page import="java.util.List" %>

<%@include file="common_imports.jsp"%>

<%

String loginId = request.getParameter("loginId"); //Group name should be come from the application based on which product or group the user belongs to.

String groupName = request.getParameter("groupName");

if( groupName == null groupName.trim().length() == 0 ) {

groupName = "Default";

}

if (loginId == null loginId.trim().length() == 0) {

String errorMessage = "Login Id was not found in the HTTP request.";

out.println(errorMessage);

} else {

loginId = loginId.trim();

groupName = groupName.trim();

BharosaHelper bharosaHelper = BharosaHelper.getInstance();

BharosaSession bharosaSession = bharosaHelper.createNewBharosaSession();

bharosaSession.setLoginId(loginId);

bharosaSession.setExternalUserId(loginId);

bharosaSession.setLocale(request.getLocale(), request.getLocales());

bharosaSession.setExternalGroupName(groupName);

String ipAddress = request.getParameter("ipAddr");

if (!StringUtil.isEmpty(ipAddress)) {

ipAddress = ipAddress.trim();

} else {

ipAddress = VCryptServletUtil.getRemoteIP(request);

}

bharosaSession.setRemoteIPAddr(ipAddress);

// Set the client's timezone offset

String clientOffsetStr = request.getParameter("clientOffset");

bharosaSession.setOffset(clientOffsetStr);

String secureCookie = getCookie(request, "bharosa");

Object[] browserFpObjects = VCryptServletUtil.getBrowserFingerPrint(request);

String browserFp = (String) browserFpObjects[1];

CookieSet cookieSet = bharosaHelper.fingerPrintBrowser(bharosaSession, bharosaSession.getRemoteIPAddr(), request.getRemoteHost(),

BharosaEnumAuthStatus.PENDING, secureCookie, browserFp);

if (cookieSet != null && cookieSet.getVCryptResponse().isSuccess()

&& cookieSet.getSecureCookie() != null) {

setCookie(request, response, "bharosa", cookieSet.getSecureCookie());

}

// Run post-authentication rules

bharosaEnumAction = bharosaHelper.runPostAuthRules(bharosaSession, BharosaHelper.getHeaderContextMap(request));

if (bharosaEnumAction == BharosaEnumAction.CHALLENGE){

out.println("POST-AUTH-CHALLENGE");

} else if (bharosaEnumAction == BharosaEnumAction.REGISTER_USER){

out.println("REG_USER");

session.setAttribute("isOptional", "false");

} else if (bharosaEnumAction == BharosaEnumAction.REGISTER_QUESTIONS){

out.println("REG_Ques");

session.setAttribute("isOptional", "false");

} else if (bharosaEnumAction == BharosaEnumAction.REGISTER_USER_OPTIONAL){

out.println("REG_USER_OPT");

session.setAttribute("isOptional", "true");

} else if (bharosaEnumAction == BharosaEnumAction.BLOCK){

out.println("BLOCK");

} else if (bharosaEnumAction == BharosaEnumAction.ALLOW){

out.println("POST-AUTH-ALLOW");

} else if (bharosaEnumAction == BharosaEnumAction.SYSTEM_ERROR){

out.println("SYSTEM_ERROR");

}

List POST_AUTH_RUNTIME_LIST = Collections.singletonList(new Integer(2));

int riskScore = bharosaHelper.runRules(bharosaSession, POST_AUTH_RUNTIME_LIST, BharosaHelper.getHeaderContextMap(request)).getScore();

out.println("Risk Score = " + riskScore);

//Store the session object the HTTP Session

BharosaUtil.storeBharosaSession(session, bharosaSession);

//Store the requestID in the session.

session.setAttribute("vcrypt_requestId",bharosaSession.getBharosaSessionId());

}

%>

Once this is in place, test the web app with a URL like:

http://<client_side_host>:<port>/webapp_sample/runRules.jsp?loginId=harry.help&clientoffset=-5&ipAddr=12.130.88.0

This JSP simply displays the action and the risk score.

I typically start with Phase 2 Post-Authentication Flow Phase 2 and add rules & conditions as necessary. You may need to change the policy to be “all users” from “linked users” to get this policy to fire.




I added a rule for restricted countries. I disabled some of the KBA checks that were pre-existing for this policy.





This is the condition that is added to the rule:











Where “Axis of Evil” is a Country group (not like Dixie Chics) that contains my blacklist of restricted countries. Here is where we set the action and alert block, as well as the risk score:







Here is an example of the session detail for the request above:




You can see the alert that results from the condition rendering true as well as the risk score and the action that results from the restricted country.

This is a very small set of the OAAM capabilities but this is intended as a bootstrap.

If you’re looking for a partner in this area, I recommend the folks at Integral who have a lot of experience with this product.

Another pattern that is interesting to me is to factor an OES attribute retriever to call ARM and write OES policies based on risk score, i.e. DENY (…) if risk_score > 500. At some point I plan to take the sample that’s floating around and make it a tidy re-usable attribute retriever.

Wednesday, December 22, 2010

Creating OES SM instances on 64 bit systems

I've already opened a bug on this against OES 10gR3 CP5, but in case anyone else runs into it before it gets fixed I wanted to blog it too. (NOTE: CP5 is when official support was introduced for running OES on a 64 bit system with a 64 bit JVM)

When you run the ConfigTool on a 64 bit Linux host you may see an error like this:

Check completed succesfully.
Starting to make changes ...
Creating SSM instance...
2010-12-22 14:36:46,952 [Main Thread] ERROR com.bea.security.SsmConfigTool.AlesConfig - Instance wizard returned error: 255
Done creating SSM instance.
Loading ALES Policy using policyloader. Please wait ...
2010-12-22 14:36:46,956 [/software/oracle/middleware/ales32-ssm/wls-ssm/instance/irmssm/bin/policyloader.sh] ERROR com.bea.security.SsmConfigTool.Daemon - Error During execution of requestd command 
java.io.IOException: java.io.IOException: /software/oracle/middleware/ales32-ssm/wls-ssm/instance/irmssm/bin/policyloader.sh: not found

As you can see the first error is that the instancewizard failed. THAT problem is probably occurring on your system because when you applied the CP you chose a 64 bit JVM but the instancewizard.sh script has a hard coded JAVA_HOME pointing to a 32 bit JVM. When the instance wizard runs (under the covers) the JVM is trying to load a 64 bit JNI library that the CP installed.

The fix?

Edit instancewizard.sh and change JAVA_HOME to point to the right JVM. Like so:

JAVA_HOME="/usr/java/latest"

Incidentally I found the root cause by running instancewizard.sh with the -log= and -log_priority= flags. You can run ./instancewazard.sh -h to get the command line help.

Tuesday, November 2, 2010

OES Security Module Logging in WebLogic domains with Enterprise Manager

This isn't the "official" solution, but a quick note on how I jury rigged my logging to get it working.

Both the OES WebLogic SM and the Enterprise Manager seem to use log4j to do their logging. Since the SM spins up first you will see the normal sorts of things you'd expect in the OES SM's log file as the SM WebLogic server boots. Then suddenly the log juts stops.

This is because the Enterprise Manager app (EM) re-initializes the log4j system with its own config file. To solve it just add the lines you want from OES' log4j.properties to the config file ./config/fmwconfig/servers/AdminServer/applications/em/META-INF/emomslogging.properties

Hope this helps someone else!

Thursday, September 16, 2010

Externalizing Authorization in PL/SQL? Inconceivable!

Ok, so it’s not a land war in Asia. But for a recent engagement, I received requirements for replacing a home-grown authorization system and doing a proof-of-concept on APEX. Eek, unsupported platform. Alright, let’s roll up our sleeves.

If there’s one thing you can find at Oracle, it’s PL/SQL expertise. I was referred to one of our rock stars, Tyler Muth, for guidance in approaching this requirement. Tyler directed me to the flex-ws-api which allows you to make PL/SQL call to a SOAP interface. OES provides a SOAP interface for authorization, so could this be love at first sight?

Flex-ws-api is pretty straightforward. You put the SOAP envelope right into the body of a CLOB data type. OES Web Service Security Module, hereto forth referred to as the Policy Decision Point or PDP, authenticates using a username-only Identity Asserter. See the OES documentation on setting up Sharepoint for instructions on this.

set serveroutput on


declare

l_BLOB BLOB;

l_CLOB CLOB;

l_envelope CLOB;

l_response_msg varchar2(32767);

l_response_xml XMLType;

procedure show_xml (p_xml in xmltype) is l_str long; begin l_str := p_xml.extract('/*').getstringval(); loop exit when l_str is null; dbms_output.put_line (substr (l_str, 1, instr (l_str, chr(10)) - 1)); l_str := substr (l_str, instr (l_str, chr(10)) + 1); end loop; end show_xml;

BEGIN

l_envelope := q'! <?xml version='1.0' encoding='UTF-8'?>!';

l_envelope := l_envelope || ' <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soap:Body>

<isAccessAllowed xmlns="http://security.bea.com/ssmws/ssm-soap-types-1.0.xsd">

<IdentityAssertion>

<sampletoken>matt.carter </sampletoken>

</IdentityAssertion>

<RuntimeResource>

<ResourceString>app/claim </ResourceString>

<AuthorityName>ARME_RESOURCE_AUTHORITY </AuthorityName>

</RuntimeResource>

<RuntimeAction>

<ActionString>view </ActionString>

<AuthorityName>ARME_ACTION_AUTHORITY </AuthorityName>

</RuntimeAction>

<RequestedCredentialType>sampletoken </RequestedCredentialType>

<AppContext>

<Record>

<q1:RecordName xmlns="" xmlns:q1="http://security.bea.com/ssmws/ssm-soap-types-1.0.xsd">attrname </q1:RecordName>

<StringValue>attrvalue </StringValue>

</Record>

</AppContext>

<AtzDirection>ALES_ONCE </AtzDirection>

</isAccessAllowed>

</soap:Body>

</soap:Envelope>';

l_response_xml := flex_ws_api.make_request(

p_url => 'http://oes-pdp:9000/Authorization',

p_action => 'isAccessAllowed',

p_envelope => l_envelope);

show_xml(l_response_xml);

END;

/

The OES response would look something like:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<soapenv:Body>

<isAccessAllowedResponse xmlns="http://security.bea.com/ssmws/ssm-soap-types-1.0.xsd">

<AccessAllowed>true </AccessAllowed>

<AtzDecisionData>

<AtzTtlAdvice>300 </AtzTtlAdvice>

</AtzDecisionData>

<ContextRequests xsi:nil="true"/>

</isAccessAllowedResponse>

</soapenv:Body>

</soapenv:Envelope>

From a database permissions side, the 10g database on the client site connected right to the PDP. In our 11g testing we found you had to set up some Access Control Lists on the database to have the database make a network connection. See this article for instructions on setting up this ACL.

The client was happy to PL/SQL and felt they could go the next step to externalizing this authorization in APEX. I haven’t accomplished this myself, so I would welcome readers to take this the next step. APEX has the capability for very fine-grained authorization and the ability to externalize this to a "PL/SQL Function returning a Boolean" type of Authorization Scheme, so it would seem APEX could call to OES for a Permit or Deny.

Special thanks to Tyler Muth for his direction on the PL/SQL side and Sri and the OES team for their guidance. Thanks to the A-Team for helping me get the word out.

mkc

Tuesday, August 3, 2010

Maven Integration for Oracle Entitlements Server

This is the final post in what has turned out to be a 3-part series in bringing to life the "hypothetical" OES-Spring integration.. This post is going to focus on the lifecycle aspect. Part of the whole value in how I designed the annotations was to allow the developer to do their work - implementing business logic - while giving enough information to security policy administrators that they could write policy in OES. I used the Java Annotation Process in JDK 1.6 to generate the actions, resources, and attributes that the runtime AuthorizationAspect would be passing to OES. This was a good start, but a long way from having the information stored in OES, let alone working in a "lifecycle".

Introducing the OES Maven Plugin


The way I attempted to address this problem was by creating a Maven plugin for OES. The OES Maven Plugin is part of the oes-jboss project. The information in this post is based on version-1.0

The plugin supports three goals (maven speak for operations)

  • import - Imports policies from the local file system into OES admin server using policyIX
  • export - Exports the policies from OES admin server and into the local file system using policyIX
  • generate-default-policy - Reads the files generated by the OES Annotations Processor and converts them into a policyIX policy file in the file system

The configuration for the plugin basically follows the names of the elements in the policyIX config file.

General Settings



  • server_host_name - Hostname of the OES Admin Server - defaults to localhost
  • server_port - SSL Port for the OES Admin Server - defaults to 7010
  • blm_server_port - The BLM API port for the OES Admin Server - defaults to 7011
  • print_info - Boolean flag that determs if the information about which objects policyIX is loading should be displayed - defaults to true
  • userID - OES Admin user id - defaults to admin
  • password - OES Admin password - defaults to password
  • policyFile - The location of the policy file that policyIX imports into the OES Admin Server or the localtion of where the generated policy file should be saved - defaults to ${project.build.outputDirectory}/com/oracle/security/entitlements/policy/policy.xml

Settings for the generate-default-policy goal



  • policyTemplateFile - the location of the policy template that the plugin should use when generating the default policies - defaults to ${project.build.outputDirectory}/com/oracle/security/entitlements/policy/policy_template.xml
  • resources - the location of the resources file generated by the OES annotations - defaults to ${project.build.outputDirectory}/com/oracle/security/entitlements/policy/object
  • actions - the location of the actions file generated by the OES annotations - defaults to ${project.build.outputDirectory}/com/oracle/security/entitlements/policy/priv
  • attributes - the location of the attributes file generated by the OES annotations -defaults to ${project.build.outputDirectory}/com/oracle/security/entitlements/policy/attr
  • overwrite - boolean indicating that the generated policies should be overwritten, even if th policyFile exists - defaults to true

Settings for the import goal



  • policy_load_procedure - the load procedure the plug in should use when importing the policies into OES - the default is override. The other valid value is delete_existing

Settings for the export goal



  • exportPolicyFile - the location of the file that the OES policies are exported to - defaults to ${project.build.sourceDirectory}/../oes/policy.xml
  • clipping_scope - the clipping scope from which the OES policies are exported - defaults to RootOrg!${oes.organization}!${oes.application}
  • createTemplateOnExport - boolean indicating that the export task should convert the OES policies into a "template", before saving it to disk - default value is true
  • replaceAdminDirInTemplate - boolean indicating that the user and group part of the policies that are defined for the AdminDir should not be templatized - default value is true

Instructions for Installing OES-Maven Plugin


The installation is really in two parts. The first is deploying a special web-application to the OES Admin server. This web-application greatly simplifies the compilation of plugin by materializing the required OES libraries as a moven POM. This is an alternative to the previously suggested ANT based approach or explicitly loading in the OES libraries. Its just too complicated, and when I realized that I needed a slighly different set of libraries to run the policyIX tool, I took the time to build the web app. With the web-app installed, you can easily build the oes-maven plugin.

Building the repository-web-app



  • Build the web-app - this is simple, just type mvn install from oes-maven/repository-web-app
  • Deploy the web-app to the OES Admin Server - This is assuming that the OES Admin Server is running on WLS, but basically, all you're doing is installing a war. You can log into the WLS admin console at https://:7010/console with admin/password, and deploy the web-app.
  • Import the OES policies protecting the web-app - We need to bootstrap the policies for who can access the oes-maven web-application. I included the policyIX policies here.

    <?xml version="1.0" encoding="UTF-8"?>
    <xb:policy_propagation xmlns:xb="http://policypropagation.ales.com/xmlbean">
    <xb:policy_propagation_data_v2>
    <xb:scopes>
    <xb:application_entry value="RootOrg!defaultOrg!oes-maven" boundSSM="asiadmin">
    <xb:admin_roles>
    <xb:admin_role_entry value="AppAdmin" isPrimary="true" description="Primary Application Admin Role of current Application">
    <xb:admin_role_privileges>
    <xb:admin_role_privilege_entry object="action" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="authorizationPolicy" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="authorizationPolicyReport" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="directory" action="adminview"/>
    <xb:admin_role_privilege_entry object="extension" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="group" action="adminview"/>
    <xb:admin_role_privilege_entry object="policyDistribution" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="policySimulator" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="resource" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="role" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="rolePolicy" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="rolePolicyReport" action="adminmanage"/>
    <xb:admin_role_privilege_entry object="user" action="adminview"/>
    </xb:admin_role_privileges>
    </xb:admin_role_entry>
    </xb:admin_roles>
    <xb:resources>
    <xb:resource_entry value="//resources/url" isVirtualResoureAllowed="true"/>
    </xb:resources>
    <xb:actions>
    <xb:action_entry value="any"/>
    </xb:actions>
    <xb:policies>
    <xb:authorization_policy_entry>
    <xb:policy_effect value="grant"/>
    <xb:policy_actions>
    <xb:policy_action_entry value="any"/>
    </xb:policy_actions>
    <xb:policy_resources>
    <xb:policy_resource_entry value="//resources/url"/>
    </xb:policy_resources>
    <xb:policy_subjects>
    <xb:policy_group_entry name="allusers" directory="AdminDir" scope="RootOrg"/>
    </xb:policy_subjects>
    </xb:authorization_policy_entry>
    </xb:policies>
    </xb:application_entry>
    </xb:scopes>
    <xb:security_configuration_data>
    <xb:scms>
    <xb:scm_entry name="adminconfig">
    <xb:ssms>
    <xb:ssm_entry name="asiadmin"/>
    <xb:ssm_entry name="jboss"/>
    <xb:ssm_entry name="oes10gR3cp4wlsssm"/>
    </xb:ssms>
    </xb:scm_entry>
    </xb:scms>
    </xb:security_configuration_data>
    </xb:policy_propagation_data_v2>
    </xb:policy_propagation>

  • Distribute The Policies - Log into the OES Entitlements Administration Server, and deploy the policies.
  • Add an entry for the OES Admin Server in your Maven's settings.xml - Since the application is protected, you'll need to have the OES admin user's credentials. In Maven, this is configured in your settings.xml

    <servers>
    <server>
    <id>oes-admin</id>
    <username>admin</username>
    <password>password</password>
    </server>
    </servers>

    The id oes-admin is just a reference used by the oes-maven-plugin POM.

Build the Plugin


From the oes-maven-plugin directory type

mvn install -Does-admin-url=http://servername:7000/oes-maven

If this works, you'll see a bunch of files downloaded to your local repository, and the oes-maven-plugin will be built successfully! For those of you who are really hard-code, you can actually access the oes-maven web-app over the SSL port by passing -Does-admin-url=https://servername:7010/oes-maven. If order to get the SSL handshake to work, you just need to import the OES Admin Server's CA into the trusted keystore of the JDK (think of this as extra credit)

Using the OES Maven Plugin - an example


I've created a 1.0.1 version of the oes-spring application that demonstrates the OES maven plugin. All of the magic is inside of the oes_spring_aop_test/pom.xml. First let's run through an example of the "lifecycle", and then we can dig into the details of the POM.

  • Developer Builds Simple Spring+OES Application - In this first step of the lifecycle, the developer is just building the objects. They add the annotations as a way to help surface the security meta-data - mainly the resources, actions, and attributes that will be available for policy authoring. As the developer compiles the application, the OES annotations are evaluated, and the OES maven plugin generates the sample policy file based on the template. You can see this by running

    mvn -Does.server.host=<hostname of admin server> compile

    The result of this is the creation of the actions, attributes, and resources files. Notice that with the sample that there were some compiler warnings generated. This is to be expected. Basically, not every Java type can be mapped to a dynamic attribute type inside of the OES console. This is fine, but you can only access these attributes via OES Attribute Retriever or Eval Function, not through the policy. In the case that you're not passing the object and its a type that is not supported in OES, then the compilation fails.
  • Developer tests application - So now the developer wants to start doing some unit testing. At this point, the OES maven plugin will generate the policyIX import file and import it into the OES admin server. The file is stored as a resource in the classes directory, and as such is expected to be a simple temporary set of policies. You can see the policies deployed to OES by running

    mvn -Does.server.host=<hostname of admin server> test

    The unit test that I have in the sample uses a dummy implemenation of the ISecurityContext, but its possible that if there was a local SM, then the policies would be available. NOTE: For the policies to take affect they need to be distributed from the OES Admin Server. The current version of the OES Maven Task does not deploy the policies
  • Security Administrator changes OES policies - The administrator can now log into the OES Admin console. You can see the resources, the actions, and the attributes that are available for policy authoring.





    The security administrator now can go in and change the policies. Since all of the resourecs, actions, and attributes have been created for them, this greatly simplifies the task. At some point, they are happy with the policies, and the policies are exported back to the project.

    mvn -Does.server.host=<hostname of admin server> oes:export

    By default, this generates a policyIX export and adds it to ${project.build.sourceDirectory}/../oes/policy.xml. This is inside of the source of the project. The expectation is that this export file would be added to source control. One interesting this that the export goal does is to change the file back into a template. This is done so that when the import goal is run, the values of a different environment can be used.
  • Policy and Application is deployed to a different environment - Once the policy hasa been exported from OES and is now part of the project, the application and policies can be moved to a different environment - say integration testing or pre-production. The POM checks to see if the OES file exists in main/oes/policy.xml, and if it does, then it uses that file (as opposed to the generated one) to be imported. You can see this by running

    mvn -Does.server.host=<hostname of admin server> install

    You'll notice that the policies that get added back to OES reflect the changes made after running oes:export - not the default policies.

Understanding a some of the oes_spring_aop POM


The project depends on a few properties

<properties>
<oes.ssm>jboss</oes.ssm>
<oes.application>jboss</oes.application>
<oes.organization>MyOrg</oes.organization>
<oes.directory>jboss_dir</oes.directory>
<oes.server.host>oel55-64.localdomain</oes.server.host>
</properties>

The first four are used for the variable substuitution inside of the policies. The properties that I ship with the project are based on the OES JBOSS SPRING application. The values for these properties should match the values used in the config tool used to create the SM. I used the built in filtering capabilities of Maven to do the variable substitution of these properties into the template.

The last property is a convenient way to specify the hostname of the admin server. Notice that in the example above, I used -Does.server.host to specify the servername. You can override any of these properties with command line arguments or as part of Maven profiles.

Summary


The way that I have the goals of the plugin tied to the phases of the Maven lifecycle is definately a matter of debate. I made a deliberate decision not to tie export to an explicit phase, but if I had to pick one...maybe deploy. My thinking is that before the application is put some place else, it makes sense to get a copy of the policies. Ultimately, I don't think there is a total one size fits all lifecycle, but I think that this OES Maven plugin, and the example project provide a very solid foundation. There are definately more goals that could be added - maybe the ability to automatically create and enroll an SM from the config tool. I'm eager to hear your feedback on the life cycle that I put forth, and what variations you've seen or think the maven plugins should support.

Friday, July 23, 2010

Oracle Entitlements Server and Spring Integration Running on JBOSS 5.1

This post is a continuation of the discussion of how to get the "hypothetical" OES+SPRING integration working on an actual platform - in this case JBOSS. This post assumes that you've already got the Java SM running inside of JBOSS 5.1. This post will focus on the technical details of the OES Spring integration and how to extend the JBOSS environment to run a sample application.

Identifying the User


In the "hypothetical" OES-Spring integrtaion post, I said that it was a fairly solved problem to figure out who the user is making the request, and this largely turned out to be true for the OES-Spring integration. I decied to make this part of the model "pluggable" and extended the AuthorizationAspect to use Spring to find an instance of the ISecurityContext interface. This is the ISecurityContext interface:

package com.oracle.oes.springaop.aspect.spi;

import com.bea.security.*;

public interface ISecurityContext {

public AuthenticIdentity getAuthenticIdentity() throws Exception;
public AuthorizationService getAuthorizationService() throws Exception;
public AuthenticationService getAuthenticationService() throws Exception;

}


It seemed logical to bundle the AuthenticIdentity and the Authorization/Authentication Services of the Java SM together. In theory, I guess you could have separarte provides of the AuthorizationService and AuthenticIdentity, but simpler is better.

Now when it came down to providing an implemenation for JBOSS, I tried the standarda Java Security - Subject.getSubject(AccessController.getAccessControllContext()) - but that didn't seem to work. Instead, the JACC Policy Context seemed to do the trick. The JBOSS Security FAQ reveals that you can use the key javax.security.auth.Subject.container to get the current subject. Very nice. Unfortunately, this subject is not acceptable by the default WLS.Subject identity asserter, so I needed a way to get an identity from the subject. Here, I went with my good friend the UsernameIdentityAsserter that ships with the product. I pull the name from the Subject and assert it. I think that a "better" implementation would be one that takes the Subject as the token. Under the covers it could still just assert the username, but it could also make use of the JBOSS roles that are included. This is a pretty simple excercise, but again for simplicity and time sake, I just went with the UsernameIdentityAsserter.

This covered the case where there actually was a user, but what about when the Spring Context is getting loaded by the container? This method returns null. I decided that the simplest thing to do was to configure the implementation of the JBOSS ISecurityContext with a username/password of a user and use that user. There are probably better implementations like - to not have the OES Authorization aspect make any calls when the container is initializing OR use something more like a run-as identity, but this was simple to do. I encourage people to try other alternatives.

Here's the relevant code:

public AuthenticIdentity getAuthenticIdentity() throws Exception {

Subject subject = (Subject)javax.security.jacc.PolicyContext.getContext("javax.security.auth.Subject.container");
System.out.println("Subject="+subject);


if (subject==null) {


System.out.println("I'll try to login with "+this.defaultUser+" "+this.defaultPassword);
AuthenticationHandler handler = new AuthenticationHandler(this.defaultUser,this.defaultPassword);

return this.getAuthenticationService().authenticate(handler);

}

//Just get the 1st principal's name

String name = ((Principal)subject.getPrincipals().iterator().next()).getName();

return this.getAuthenticationService().assertIdentity("USERID_TOKEN", name );

}

I pulled all of this together into a separate POM (oes.jboss.spring.securitycontext) that also includes the Spring configuration. The only thing interesting is that this is is where the username and password for the administration user are specified

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<bean name="securityContext" class="com.oracle.security.entitlements.jbosssecuritycontext.JBOSSSecurityContext">
<property name="defaultUser">
<value>admin</value>
</property>
<property name="defaultPassword">
<value>password</value>
</property>
</bean>

</beans>

Since we're using the OES API, this user is going to be authenticated by OES (not JBOSS).

Adding Spring AOP to JBOSS Web Application


I don't want to dwell on this too much, but in pulling this sample together, I did stumble in getting the LTW to work. With eough googling, you find that you need project Snowdrop. So, instead of using the default loadtime weaver, you use the one from Snowdrop

<context:load-time-weaver weaver-class="org.jboss.instrument.classloading.JBoss5LoadTimeWeaver"/>

Building the oes-spring project


I continue to be very impressed with Maven - (I know - what took me so long), but it really made putting this thing together incredible simple. You can build the project from the version-1.0 tag from the subversion repository. The project is a collection of the following modules:

  • oes_spring_aop - The core annotations and aspects of the Spring/OES/AOP integration
  • oes_spring_aop_test - A test application and "dummy" ISecurityContext that demonstrates the OES annotations
  • oes.jboss.spring.securitycontext - The ISecurityContext implementation for JBOSS
  • jboss-sample-web - A sample web-application that shows the oes_spring_aop_test application run inside of a web-application running on JBOSS

Configuring JBOSS for running jboss-sample-web


There is a little bit of set-up that is required in order to run the jboss-sample-webapplication.

  • Modify run_with_oes.conf - The JBOSS start script needs to be modified to include the -javaagent setting to enable the Spring LTW.

    if [ "x$JAVA_OPTS" = "x" ]; then
    JAVA_OPTS="-Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -javaagent:/path to spring/spring-framework-2.5.6.SEC02/dist/weaving/spring-agent.jar $JAVA_OPTIONS"
    fi

    You can either reference the spring-agent.jar from the repository or download it from springsource
  • Modify the server/default/conf/login-config.xml - The JBOSS web-app is protected with JEE security. The application requires the user to be in the role oes_users role. You can do this by configuring JBOSS to use simple files to define users and their passwords, and users and their roles.

    <application-policy name="other">
    <!--
    A simple server login module, which can be used when the number
    of users is relatively small. It uses two properties files:
    users.properties, which holds users (key) and their password (value).
    roles.properties, which holds users (key) and a comma-separated list of
    their roles (value).
    The unauthenticatedIdentity property defines the name of the principal
    that will be used when a null username and password are presented as is
    the case for an unuathenticated web client or MDB. If you want to
    allow such users to be authenticated add the property, e.g.,
    unauthenticatedIdentity="nobody"
    -->
    <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
    flag="optional">
    <module-option name="usersProperties">oes-users.properties</module-option>
    <module-option name="rolesProperties">oes-roles.properties</module-option>
    <module-option name="unauthenticatedIdentity">anonymous</module-option>
    </login-module>
    </authentication>
    </application-policy>

    Put the oes-users.properties and oes-roles.properties in the same directory as login-config.xml. For example:
    oes-users.properties
    josh=password
    oes-roles.properties
    josh=oes_user
  • Deploy the application - Start JBOSS and goto servername:8080/admin-console. Log in with username admin password admin. You can deploy the web-application by simply uploading the .war. Alternatively, if JBOSS is running on the same machine, simply copy the .war to server/default/deploy

Testing the application with OES


Here is the policyIX export for the sample application

<?xml version="1.0" encoding="UTF-8"?>
<xb:policy_propagation xmlns:xb="http://policypropagation.ales.com/xmlbean">
<xb:policy_propagation_data_v2>
<xb:scopes>
<xb:application_entry value="RootOrg!MyOrg!jboss" boundSSM="jboss">
<xb:application_attributes>
<xb:application_attribute_entry name="sys_obj_allow_virtual" ASIType="boolean">
<xb:single_value_entry value="true"/>
</xb:application_attribute_entry>
</xb:application_attributes>
<xb:admin_roles>
<xb:admin_role_entry value="AppAdmin" isPrimary="true" description="Primary Application Admin Role of current Application">
<xb:admin_role_privileges>
<xb:admin_role_privilege_entry object="action" action="adminmanage"/>
<xb:admin_role_privilege_entry object="authorizationPolicy" action="adminmanage"/>
<xb:admin_role_privilege_entry object="authorizationPolicyReport" action="adminmanage"/>
<xb:admin_role_privilege_entry object="directory" action="adminview"/>
<xb:admin_role_privilege_entry object="extension" action="adminmanage"/>
<xb:admin_role_privilege_entry object="group" action="adminview"/>
<xb:admin_role_privilege_entry object="policyDistribution" action="adminmanage"/>
<xb:admin_role_privilege_entry object="policySimulator" action="adminmanage"/>
<xb:admin_role_privilege_entry object="resource" action="adminmanage"/>
<xb:admin_role_privilege_entry object="role" action="adminmanage"/>
<xb:admin_role_privilege_entry object="rolePolicy" action="adminmanage"/>
<xb:admin_role_privilege_entry object="rolePolicyReport" action="adminmanage"/>
<xb:admin_role_privilege_entry object="user" action="adminview"/>
</xb:admin_role_privileges>
</xb:admin_role_entry>
</xb:admin_roles>
<xb:resources>
<xb:resource_entry value="//resources/Person" isVirtualResoureAllowed="true"/>
</xb:resources>
<xb:actions>
<xb:action_entry value="any"/>
<xb:action_entry value="readConfidential"/>
<xb:action_entry value="txfer"/>
</xb:actions>
<xb:dynamic_attributes>
<xb:dynamic_attribute_entry name="amount" type="integer"/>
</xb:dynamic_attributes>
<xb:roles>
<xb:role_entry value="Anonymous" parent=""/>
<xb:role_entry value="Everyone" parent=""/>
</xb:roles>
<xb:policies>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="any"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="weblogic" directory="jboss_dir" scope="RootOrg!MyOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="readConfidential"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/Person"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="josh" directory="jboss_dir" scope="RootOrg!MyOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="any"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="admin" directory="AdminDir" scope="RootOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="txfer"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/Person"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="josh" directory="jboss_dir" scope="RootOrg!MyOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="sys_defined ( amount ) and amount &lt; 75"/>
</xb:authorization_policy_entry>
</xb:policies>
</xb:application_entry>
</xb:scopes>
<xb:security_configuration_data>
<xb:scms>
<xb:scm_entry name="adminconfig">
<xb:ssms>
<xb:ssm_entry name="asiadmin"/>
<xb:ssm_entry name="jboss"/>
<xb:ssm_entry name="oes10gR3cp4wlsssm"/>
</xb:ssms>
</xb:scm_entry>
</xb:scms>
</xb:security_configuration_data>
</xb:policy_propagation_data_v2>
</xb:policy_propagation>


  • Load this policy into OES.
  • Test the application, by going to http://servername:8080/jboss-sample-web-1.0/OESTest.jsp
  • Login with the username and password you added to the oes_user.properties (josh/password)
  • You get access to the sample application

Summary


This is a working example of the runtime aspects of the OES Spring integration working in an actual environment. The code is now available at https://oes-spring.samplecode.oracle.com. I'm really happy (with the help of Maven) how easy is was to pull all of this together. The admin story, still needs some work. Even though the annotations are generating data in a flat file format that OES can understand, its not integrated into the build process. As you saw from the example, I had to give you the export of the policies I worked with....not part of the maven process. I'd be interested in getting people's feedback on this issue - how do think that OES policy should be tied into the overall lifecycle in a scenario like this? I'll share with you my thoughts shortly