In the January / February issue of Oracle magazine, Frank Nimphius wrote a good article on ADF security and OPSS policies. The article includes a good sample application that utilizes ADF and OPSS security, along with a pretty thorough explanation of how the sample application works and was created. You can find the article which includes a link to the sample application download here.
Showing posts with label opss. Show all posts
Showing posts with label opss. Show all posts
Monday, March 12, 2012
Monday, October 17, 2011
The “reassociation” business
Since Fusion Middleware 11.1.1.4, OPSS (Oracle Platform Security Services) support 3 types of security stores: file, OID (Oracle Internet Directory) and Oracle database. When a Weblogic server domain is first created, OPSS is “associated” to a file-based security store by default, which is ok for development purposes. But for production, that is not recommended (Please check Multiple Nodes Servers Environments section in OPSS docs). That would be ok if your whole environment is a single Weblogic domain with only one server in a single machine. But 99,99% of the cases are not like that. Usually, an SOA or WebCenter environment is composed of multiple servers in clusters spread across different machines. A file-based security store is not a scalable option. In these cases, you should look at OID or the database. Fusion Applications, a gigantic set of apps, adopt OID as the security store.
The OPSS security store is a composite of policies, credentials, keys and audit services. Notice that I am leaving the identity store service out. OPSS delegates the identity store service to the identity providers configured in WebLogic server.
As a side note, OPSS is not a product, but a set of security services used by Fusion Middleware. If you’re a Fusion Middleware user, trying to understand OPSS is a great idea.
This post is about the nitty-gritty details of configuring (or reassociating) a Weblogic server domain (or multiple domains) to a different type of security store. That’s where the term “reassociation” comes from.
The information presented here is a small subset, but complements and sometimes overlaps “Configuring OPSS Security Store” documentation (reading is strongly recommended).
Before going any further on reassociation, let me talk a bit about an important character: jps-config.xml.
This is the OPSS file that describes all its services. It is located through the –Doracle.security.jps.config system property, which is set in setDomainEnv.sh script in a standard JRF (Java Required Files) domain. By the default, the property points to ${DOMAIN_HOME}/config/fmwconfig/jps-config.xml and it is defined in the variable EXTRA_JAVA_PROPERTIES. It is NOT a good idea to change it, since jps-config.xml holds several relative references to other files.
The OPSS security store is a composite of policies, credentials, keys and audit services. Notice that I am leaving the identity store service out. OPSS delegates the identity store service to the identity providers configured in WebLogic server.
As a side note, OPSS is not a product, but a set of security services used by Fusion Middleware. If you’re a Fusion Middleware user, trying to understand OPSS is a great idea.
This post is about the nitty-gritty details of configuring (or reassociating) a Weblogic server domain (or multiple domains) to a different type of security store. That’s where the term “reassociation” comes from.
The information presented here is a small subset, but complements and sometimes overlaps “Configuring OPSS Security Store” documentation (reading is strongly recommended).
Before going any further on reassociation, let me talk a bit about an important character: jps-config.xml.
jps-config.xml
This is the OPSS file that describes all its services. It is located through the –Doracle.security.jps.config system property, which is set in setDomainEnv.sh script in a standard JRF (Java Required Files) domain. By the default, the property points to ${DOMAIN_HOME}/config/fmwconfig/jps-config.xml and it is defined in the variable EXTRA_JAVA_PROPERTIES. It is NOT a good idea to change it, since jps-config.xml holds several relative references to other files.
Labels:
jpsconfig,
oid,
opss,
reassociation,
securitystore
Friday, October 7, 2011
Virtual Users in OIF, Weblogic and OWSM
One of the main strengths of SAML is the ability to communicate identity information across security domains that do not necessarily share the same user base. In other words, the authenticated user in one security domain does not necessarily exist in the target security domain providing the service.
Such concept is supported in all major Oracle products that consume SAML tokens: OIF, Weblogic Server and OWSM. The sole purpose of this post is to show how to configure it in these products. Setting up SAML services as a whole involves more than what’s showed here and I recommend the official product documentation for detailed steps.
I hope this can be helpful to someone out there.
OIF enables federated single sign on for users behind a web browser.
It calls the aforementioned concept “Transient Federation” and enables it via a checkbox (that should be unchecked) in Enterprise Manager OIF’s Console. Notice it also supports the concept of a "Mapped Federation", where the incoming identity is mapped to some generic user in the local identity store. But here I am talking about the case where there's no mapping. The user in the SAML assertion is simply trusted.
In order to enable a Transient Federation in OIF, simply make sure “Map Assertion to User Account” checkbox is unchecked in the Service Provider Common tab.
Weblogic server provides SAML services that can be leveraged by Web SSO as well web services.
Weblogic calls the concept Virtual Users and implements it in its SAML2IdentityAsserter along with the SAMLAuthenticator.
First, you need to enable your server as a SAML Service Provider. Notice this is done at the server level. Go to Environment –> servers –> <Pick server from list> to get into the screen below:
Then add a SAML2IdentityAsserter to the authentication providers list and add an Identity Provider (who does not need to be another Weblogic server) Partner to SAML2IdentityAsserter. Notice that you can add either a Web SSO partner provider or a Web service partner provider. In the case of Web SSO, Weblogic Console will ask you for the partner metadata file.
Such concept is supported in all major Oracle products that consume SAML tokens: OIF, Weblogic Server and OWSM. The sole purpose of this post is to show how to configure it in these products. Setting up SAML services as a whole involves more than what’s showed here and I recommend the official product documentation for detailed steps.
I hope this can be helpful to someone out there.
OIF (Oracle Identity Federation)
OIF enables federated single sign on for users behind a web browser.
It calls the aforementioned concept “Transient Federation” and enables it via a checkbox (that should be unchecked) in Enterprise Manager OIF’s Console. Notice it also supports the concept of a "Mapped Federation", where the incoming identity is mapped to some generic user in the local identity store. But here I am talking about the case where there's no mapping. The user in the SAML assertion is simply trusted.
In order to enable a Transient Federation in OIF, simply make sure “Map Assertion to User Account” checkbox is unchecked in the Service Provider Common tab.
Weblogic Server
Weblogic server provides SAML services that can be leveraged by Web SSO as well web services.
Weblogic calls the concept Virtual Users and implements it in its SAML2IdentityAsserter along with the SAMLAuthenticator.
First, you need to enable your server as a SAML Service Provider. Notice this is done at the server level. Go to Environment –> servers –> <Pick server from list> to get into the screen below:
Then add a SAML2IdentityAsserter to the authentication providers list and add an Identity Provider (who does not need to be another Weblogic server) Partner to SAML2IdentityAsserter. Notice that you can add either a Web SSO partner provider or a Web service partner provider. In the case of Web SSO, Weblogic Console will ask you for the partner metadata file.
Labels:
federation,
opss,
owsm,
transient,
virtualusers,
weblogic
Thursday, April 14, 2011
Watch out those code source grants
Code source grants are policies governing the rights of code running in a JVM (Java Virtual Machine). In this article, I talk about 3 common implementation issues when dealing with code source grants in a Weblogic/OPSS (Oracle Platform Security Services) environment.
Code requiring grants are one of the protection mechanisms offered in the Java platform since Java SE 1.2. Java SE 1.2 improved the previous versions by allowing a fine-grained authorization model, opposed to the all-or-nothing model in Java SE 1.0 and 1.1.
In a nutshell, if you want to only allow code from a given jar file to read/write to a file in tmp folder, you can specify the following in one of the java.policy files:
The code base grant along with the permission define what is known as a protection domain.
Then when you run the JVM with the security manager enabled (-Djava.security.manager), any code attempting to read/write to /tmp folder will be checked if it has been granted the permission.
Fair enough.
OPSS does not use the standard java.policy. Instead, it implements JAAS by looking at the configured policy store repository (system-jazn-data.xml by default) as the policy store for code source grants (as well as principal-based grants). Here’s a snippet:
Lines 28-43 define the code source grant in OPSS standards. Notice it actually resembles a plain java code grant pretty well. This specific grant allows any code deployed under file:${domain.home}/servers/${weblogic.Name}/tmp/_WL_user/MyApp to getApplicationPolicy in the MyApp application policy context.
This leads us to issue #1.
In system-jazn-data.xml, principal-based grants are application-scoped, meaning they’re meaningful for a specific application and are defined within the <application> element. Code source grants are referred to as system grants and are defined in the outermost <jazn-policy> element, outside of any <application> element. OPSS is very strict when it comes to policies in LDAP. It won’t accept system grants in application scope.
And if you use the embedded Weblogic server in JDeveloper, applications are read from another location: ${domain.home}/../o.j2ee/drs/<application-name>
As a result, code source grants in the policy files must be aligned to the server staging mode.
<application-name> is the actual deployed application name.
It’s a good idea to have something in the build system to target the system grants appropriately to your actual testing and production environments.
However, the JVM gives us the option of calling the secured API inside an AccessController.doPrivileged block. In this way the JVM gets signaled to not check permissions further up in the call chain. In other words, the protection domain containing that block gets entitled to execute the operation on behalf of anyone calling it without the need of granting anyone else. Here’s some sample code:
Lines 5-10 make the getAplicationPolicy method executable by granting only the corresponding protection domain (and nobody else) in the policy store, exactly as in the system-jazn-data.xml shown above.
AccessController.doPrivileged expects either a PrivilegedAction or a PrivilegedExceptionAction type. Both define the run method, where the protected API call is to be made.
It is important that such an approach gets combined with other protection mechanisms, otherwise other code deployed in the container could leverage the privileged code in some “uncool” manner. And if you make that code available to external clients, make sure those interfaces are properly secured (well, this also applies to any sensitive aspect that you expose, regardless of AccessController.doPrivileged usage).
Code requiring grants are one of the protection mechanisms offered in the Java platform since Java SE 1.2. Java SE 1.2 improved the previous versions by allowing a fine-grained authorization model, opposed to the all-or-nothing model in Java SE 1.0 and 1.1.
In a nutshell, if you want to only allow code from a given jar file to read/write to a file in tmp folder, you can specify the following in one of the java.policy files:
1: grant codeBase “file://MyApp/MyJar.jar” 2: { 3: permission java.io.FilePermission “/tmp/*” “read/write”; 4: }Then when you run the JVM with the security manager enabled (-Djava.security.manager), any code attempting to read/write to /tmp folder will be checked if it has been granted the permission.
Fair enough.
OPSS does not use the standard java.policy. Instead, it implements JAAS by looking at the configured policy store repository (system-jazn-data.xml by default) as the policy store for code source grants (as well as principal-based grants). Here’s a snippet:
1: <jazn-data>
2: <policy-store>
3: <applications>
4: <application>
5: <name>MyApp</name>
6: <jazn-policy>
7: <grant>
8: <grantee>
9: <principals>
10: <principal>
11: <class>oracle.security.jps.internal.core.principals.JpsAuthenticatedRoleImpl</class>
12: <name>authenticated-role</name>
13: </principal>
14: </principals>
15: </grantee>
16: <permissions>
17: <permission>
18: <class>oracle.adf.share.security.authorization.RegionPermission</class>
19: <name>trunk.pagedefs.SearchPageDef</name>
20: <actions>view</actions>
21: </permission>
22: </permissions>
23: </grant>
24: </jazn-policy>
25: </application>
26: </applications>
27: </policy-store>
28: <jazn-policy>
29: <grant>
30: <grantee>
31: <codesource>
32: <url>file:${domain.home}/servers/${weblogic.Name}/tmp/_WL_user/MyApp/-</url>
33: </codesource>
34: </grantee>
35: <permissions>
36: <permission>
37: <class>oracle.security.jps.service.policystore.PolicyStoreAccessPermission</class>
38: <name>context=APPLICATION,name=MyApp</name>
39: <actions>getApplicationPolicy</actions>
40: </permission>
41: </permissions>
42: </grant>
43: </jazn-policy>
44: </jazn-data>
Lines 28-43 define the code source grant in OPSS standards. Notice it actually resembles a plain java code grant pretty well. This specific grant allows any code deployed under file:${domain.home}/servers/${weblogic.Name}/tmp/_WL_user/MyApp to getApplicationPolicy in the MyApp application policy context.
This leads us to issue #1.
Code source grants must be defined separately from principal-based grants.
In system-jazn-data.xml, principal-based grants are application-scoped, meaning they’re meaningful for a specific application and are defined within the <application> element. Code source grants are referred to as system grants and are defined in the outermost <jazn-policy> element, outside of any <application> element. OPSS is very strict when it comes to policies in LDAP. It won’t accept system grants in application scope.
Observe Weblogic server staging mode.
Within a grant definition, the codesource url element refers to its physical location in the file system. Weblogic server deploys bits into different locations depending on its staging mode. In stage mode, application bits are copied from the AdminServer to a specific directory in the managed servers. By default it is ${domain.home}/servers/${weblogic.Name}/tmp/_WL_user/<application-name>/ (or whatever specified by the staging directory name attribute). In nostage mode, applications are, by default, laid down at ${domain.name}/servers/AdminServer/upload/<application-name>/.And if you use the embedded Weblogic server in JDeveloper, applications are read from another location: ${domain.home}/../o.j2ee/drs/<application-name>
As a result, code source grants in the policy files must be aligned to the server staging mode.
<application-name> is the actual deployed application name.
It’s a good idea to have something in the build system to target the system grants appropriately to your actual testing and production environments.
Know about AccessController.doPrivileged when invoking protected APIs
The JVM security model correctly takes a conservative approach when evaluating code source grants in the sense that it does not allow a piece of code to “do stuff” in behalf of other another piece of code unless explicitly stated by the application developer. Imagine if you had the rights to delete the contents of a folder and did that upon anyone’s request. Bad things would happen. So the JVM enforces the concept of a trusted path, meaning that whenever a secured operation is called, a permission check is made against all protection domains in the call chain in that executing thread. And this means every protection domain in that call chain must be granted the permission in the policy store. Obviously, the correct set of grants can get very tricky, especially if you’re writing code that is invoked as part of some framework that is also invoked off another framework... You can spend a considerable amount of work figuring out the right code source URLs.However, the JVM gives us the option of calling the secured API inside an AccessController.doPrivileged block. In this way the JVM gets signaled to not check permissions further up in the call chain. In other words, the protection domain containing that block gets entitled to execute the operation on behalf of anyone calling it without the need of granting anyone else. Here’s some sample code:
1: JpsContextFactory f = JpsContextFactory.getContextFactory(); 2: JpsContext c = f.getContext(); 3: final PolicyStore ps = c.getServiceInstance(PolicyStore.class); 4: final String appId = "MyApp"; 5: ApplicationPolicy ap = AccessController.doPrivileged(new 6: PrivilegedExceptionAction<ApplicationPolicy>() {
7: public ApplicationPolicy run() throws PolicyStoreException { 8: return ps.getApplicationPolicy(appId); 9: } 10: }, null); 11: // Continue with the ap object for policy operations.Lines 5-10 make the getAplicationPolicy method executable by granting only the corresponding protection domain (and nobody else) in the policy store, exactly as in the system-jazn-data.xml shown above.
AccessController.doPrivileged expects either a PrivilegedAction or a PrivilegedExceptionAction type. Both define the run method, where the protected API call is to be made.
It is important that such an approach gets combined with other protection mechanisms, otherwise other code deployed in the container could leverage the privileged code in some “uncool” manner. And if you make that code available to external clients, make sure those interfaces are properly secured (well, this also applies to any sensitive aspect that you expose, regardless of AccessController.doPrivileged usage).
Labels:
AccessController,
codesource,
grant,
opss,
weblogic
Monday, February 28, 2011
OPSS Sample Application available on samplecode.oracle.com
Just a quick post to let anyone interested know that the OPSS sample mentioned on the blog a while back has been uploaded to SampleCode. You can get it at https://opss_sample_code.samplecode.oracle.com/
Labels:
opss
Monday, September 27, 2010
OPSS Artifacts Life Cycle in ADF applications
After writing about users and groups migration, it looked to me we should also talk about the life cycle of other important entities in secured ADF applications. When you enable security in an ADF application, you see a couple of new artifacts in your JDeveloper workspace, namely jps-config.xml, jazn-data.xml and cwallet.sso.
Have you ever wondered what their purpose is, their life cycle and how they relate to WLS domain security configuration? This article is just about it.
As you might know, secured ADF applications leverage OPSS (Oracle Platform Security Services). OPSS is a fundamental component within Oracle Fusion Middleware security. It works as an abstraction layer on top of security services providers, shielding applications from all the complexities in dealing with them. For instance, applications can transparently switch between file-based and LDAP-based policy stores. Likewise for credential store services.
Let's take a closer look at each of those artifacts and their life cycles.
This file can be seen as the lookup services registry for OPSS. Among these services are login modules, authentication providers, authorization policy providers, credential stores and auditing services.
Whenever an OPSS-enabled application requires security services, it looks up a JPSContext object where all the necessary services are supposedly configured.
In ADF applications, a workspace-level jps-config.xml is created once ADF security is enabled. It drives services lookup for ADF's BC (Business Components) Tester available in JDeveloper, which is a JavaSE application. If you want to have security unit tests, you can also easily leverage it.
It is never used once the ADF application gets deployed in a WLS container, even though it is packaged in the ear file. Within a WLS container, a jps-config.xml in <domain-home>/config/fmwconfig is used by all applications in all servers deployed in that WLS domain. There's no such concept of an application-level or server-level jps-config.xml.
This file keeps users, groups and authorization policies for OPSS-enabled applications and is automatically created once ADF security is enabled. I've already covered users and groups life cycles in a previous article. It is important to mention that users and groups are also leveraged by ADF's BC Tester and can be integrated into security unit tests as well.
Authorization policies are, if not the most, one of the most sensitive parts of a secured ADF application, since it governs who has access to what. As you might guess, they are also leveraged by ADF's BC Tester. When the ADF application is deployed into WLS, at startup time, policies are OOTB (Out-Of-The-Box) migrated into the configured policy store, who, by default, is a file called system-jazn-data.xml, located under <domain-home>/config/fmwconfig. You can configure how (and if) policies are migrated through some properties in weblogic-application.xml. Here they are:
This listener is the one actually responsible for pushing the changes to the runtime policy store. Make sure it is present in weblogic-application.xml. Otherwise, you’ll experience a lot of frustration in trying to deploy authorization policies along with your application.
MERGE, OVERWRITE and OFF are exclusive and applicable for deployments and redeployments. And they mean exactly what you might be thinking.
Authorization policies migration will always happen according to weblogic-application.xml configuration, no matter what the deployment method is.
This file keeps credentials used by the application. A subtle and fundamental distinction is important to be made here: credentials and identities are not the same thing. Simply put, in OPSS, identities are what authentication requests are done against, while credentials are securely kept objects that are somehow presented to authentication providers to be matched against identities.
cwallet.sso is encrypted and you cannot browse it or explicitly edit it via JDeveloper. At design-time, different components make use of cwallet.sso and are responsible for creating the necessary credentials in it. Examples are OWSM policy attachments that override the csf-key and ADF connections requiring credentials in the call out.
If you need credentials that can’t be created within JDeveloper, you can either use wlst createCred online command or write some code using OPSS APIs. Both options makes the whole life cycle story a little catchy, because a running WLS container is necessary. You can also disable credentials migration and create them directly in the WLS domain where applications are deployed.
Like authorization policies, credentials are also OOTB migrated into the configured WLS domain credential store on application startup. By default, the credential store is the cwallet.sso file in <domain-home>/config/fmwconfig folder.
The following weblogic-application.xml properties govern how (and if) they're deployed.
As for policies, the same listener migrates credentials. Avoid frustration and make sure the listener is present if you want to migrate or control how your credentials are migrated.
Have you ever wondered what their purpose is, their life cycle and how they relate to WLS domain security configuration? This article is just about it.
As you might know, secured ADF applications leverage OPSS (Oracle Platform Security Services). OPSS is a fundamental component within Oracle Fusion Middleware security. It works as an abstraction layer on top of security services providers, shielding applications from all the complexities in dealing with them. For instance, applications can transparently switch between file-based and LDAP-based policy stores. Likewise for credential store services.
Let's take a closer look at each of those artifacts and their life cycles.
jps-config.xml
This file can be seen as the lookup services registry for OPSS. Among these services are login modules, authentication providers, authorization policy providers, credential stores and auditing services.
Whenever an OPSS-enabled application requires security services, it looks up a JPSContext object where all the necessary services are supposedly configured.
In ADF applications, a workspace-level jps-config.xml is created once ADF security is enabled. It drives services lookup for ADF's BC (Business Components) Tester available in JDeveloper, which is a JavaSE application. If you want to have security unit tests, you can also easily leverage it.
It is never used once the ADF application gets deployed in a WLS container, even though it is packaged in the ear file. Within a WLS container, a jps-config.xml in <domain-home>/config/fmwconfig is used by all applications in all servers deployed in that WLS domain. There's no such concept of an application-level or server-level jps-config.xml.
jazn-data.xml
This file keeps users, groups and authorization policies for OPSS-enabled applications and is automatically created once ADF security is enabled. I've already covered users and groups life cycles in a previous article. It is important to mention that users and groups are also leveraged by ADF's BC Tester and can be integrated into security unit tests as well.
Authorization policies are, if not the most, one of the most sensitive parts of a secured ADF application, since it governs who has access to what. As you might guess, they are also leveraged by ADF's BC Tester. When the ADF application is deployed into WLS, at startup time, policies are OOTB (Out-Of-The-Box) migrated into the configured policy store, who, by default, is a file called system-jazn-data.xml, located under <domain-home>/config/fmwconfig. You can configure how (and if) policies are migrated through some properties in weblogic-application.xml. Here they are:
<listener>
<listener-class>oracle.security.jps.wls.listeners.JpsApplicationLifecycleListener<listener-class>
<listener>
This listener is the one actually responsible for pushing the changes to the runtime policy store. Make sure it is present in weblogic-application.xml. Otherwise, you’ll experience a lot of frustration in trying to deploy authorization policies along with your application.
<application-param>
<param-name>jps.policystore.migration</param-name>
<param-value>[MERGE|OVERWRITE|OFF]</param-value>
</application-param>
MERGE, OVERWRITE and OFF are exclusive and applicable for deployments and redeployments. And they mean exactly what you might be thinking.
- MERGE will merge what’s already available in the runtime policy store. This might be particularly useful in some advanced deployments where more than one application share the same application policy stripe.
- OVERWRITE wipes away the existing application policy stripe and load all policies from scratch.
- OFF skips policy migration.
<application-param>
<param-name>jps.policystore.removal</param-name>
<param-value>OFF</param-value>
</application-param>
cwallet.sso
This file keeps credentials used by the application. A subtle and fundamental distinction is important to be made here: credentials and identities are not the same thing. Simply put, in OPSS, identities are what authentication requests are done against, while credentials are securely kept objects that are somehow presented to authentication providers to be matched against identities.
cwallet.sso is encrypted and you cannot browse it or explicitly edit it via JDeveloper. At design-time, different components make use of cwallet.sso and are responsible for creating the necessary credentials in it. Examples are OWSM policy attachments that override the csf-key and ADF connections requiring credentials in the call out.
If you need credentials that can’t be created within JDeveloper, you can either use wlst createCred online command or write some code using OPSS APIs. Both options makes the whole life cycle story a little catchy, because a running WLS container is necessary. You can also disable credentials migration and create them directly in the WLS domain where applications are deployed.
Like authorization policies, credentials are also OOTB migrated into the configured WLS domain credential store on application startup. By default, the credential store is the cwallet.sso file in <domain-home>/config/fmwconfig folder.
The following weblogic-application.xml properties govern how (and if) they're deployed.
<listener>
<listener-class>oracle.security.jps.wls.listeners.JpsApplicationLifecycleListener</listener-class>
</listener>
As for policies, the same listener migrates credentials. Avoid frustration and make sure the listener is present if you want to migrate or control how your credentials are migrated.
<application-param>
<param-name>jps.credstore.migration</param-name>
<param-value>[MERGE|OVERWRITE|OFF]</param-value>
</application-param>
- MERGE: migrate non-existing credentials only;
- OVERWRITE: overwrites existing credentials;
- OFF: skips credentials migration;
Labels:
ADF security,
cwallet.sso,
jazn-data.xml,
JDeveloper,
jps-config.xml,
opss,
Oracle,
policies,
security
Tuesday, September 8, 2009
SAML Bearer Confirmation - An example using OWSM Client Policy
This is an extension of the discussion started by Brian in his inaugural post here at the FusionSecurity blog. Brian and I, along with other members of the A-Team were out at HQ getting some training on the SOA Security capabilities in 11g, and I wanted to share a useful "How-To" from that week.
First, let me show you the code, and then I'll take you through the code in some details and explain the additional set-up required to make this use case work. Basically, the code is for a stand-alone Java client using OWSM client policies to enable a JAX-WS Web Service Proxy to use SAML Bearer over SSL - quite a mouthful!
The Code
We're applying OWSM client side policy, that requires a SAML Assertion - Bearer and that the request is over SSL. The SSL implementation is the standard J2SE and OWSM uses the JAAS Subject for the identity. The policy is applied via the WebServiceFeature and is described in the OWSM documentation.
Basically, we're using OPSS inside of a J2SE client to establish the JAAS Subject, without providing a password. I used the OPSS documentation as a reference. I used exactly the MyAssertionCallbackHandler from the documentation.
The final "trick" is that the call to the web service is done inside of a call to Subject.doAs(Subejct,PriviledgedAction). This pushes the Subject from the LoginModule on to call stack, and makes it available for the OWSM policy.
So, there a few command line arguments that need to be passed to this client:
-Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=123456
There are the standard J2SE SSL parameters. The JAX-WS client uses the standard SSL.
In my example, I just used the DemoIdentity and DemoTrust, so I set my -D's to
-Djavax.net.ssl.trustStore=C:\\Oracle\\Middleware\\wlserver_10.3\\server\\lib\\DemoTrust.jks -Djavax.net.ssl.trustStorePassword=DemoTrustKeyStorePassPhrase
You also have to pass the program the location of the jps-config.xml.
-Doracle.security.jps.config=c:\jps-config-jse.xml
The jps-config.xml defines the Oracle Platform Security (OPSS) services used by the client. In our use-case, we're going to be using the LoginService to establish an identity for the client. I got the basis of the jps-config-jse.xml from DOMAIN_HOME\config\fmwconfig\jps-config.jse.xml.
At the end of this file, you need to add a jpsContext called Client that contains a reference to the user.assertion.loginmodule
The user assertion login module allows the client to create an identity for the user with no password. It won't work with any username - the user still has to be found in the identity store, which in this case is stored inside of the system-jazn-data.xml. By default, the login module is looking for the system-jazn-data.xml found in the same directory in the jps-config.xml.
I found the system-jazn-data.xml reference useful in building this file:
The final, configuration step is to make sure that the user that you're asserting - in this case "josh" exists on the server side in WLS. You can just add the user via the WLS admin console.
This is definitely a little tricky, but it demonstrates how to use a SAML Bearer assertion. There is no PKI required on the client side - simply the ability to trust the server at the transport level. This is pretty straight forward and simpler then setting-up either sender-vouches or holder-of-key. Consider using this type of approach from within a trusted network.
First, let me show you the code, and then I'll take you through the code in some details and explain the additional set-up required to make this use case work. Basically, the code is for a stand-alone Java client using OWSM client policies to enable a JAX-WS Web Service Proxy to use SAML Bearer over SSL - quite a mouthful!
The Code
package com.oracle.team2.view;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.WebServiceRef;
import oracle.security.jps.JpsContext;
import oracle.security.jps.JpsContextFactory;
import oracle.security.jps.service.login.LoginService;
public class MyWebServicePortClient {
@WebServiceRef
private static MyWebServiceService myWebServiceService;
public static void main(String[] args) throws Exception {
URL localURL =
new URL("https://.../MyWebServicePort?WSDL");
QName name =
new QName("http://view.team2.oracle.com/", "MyWebServiceService");
myWebServiceService = new MyWebServiceService(localURL, name);
JpsContextFactory factory =
JpsContextFactory.getContextFactory();
JpsContext jpsContext = factory.getContext("Client");
LoginService loginService =
jpsContext.getServiceInstance(LoginService.class);
CallbackHandler cbh = new MyAssertionCallbackHandler("josh");
String[] selectiveModules = new String[] {
"user.assertion.loginmodule"
};
LoginContext ctx =
loginService.getLoginContext(new Subject(), cbh, selectiveModules);
ctx.login();
Subject s = ctx.getSubject();
final weblogic.wsee.jws.jaxws.owsm.SecurityPolicyFeature securityFeature =
new weblogic.wsee.jws.jaxws.owsm.SecurityPolicyFeature(
"policy:oracle/wss_saml_token_bearer_over_ssl_client_policy");
Subject theSubject =
Subject.getSubject(AccessController.getContext());
System.out.println("The Subject is " + theSubject);
AccessControlContext acc =
AccessController.getContext();
Subject.doAs(s, new PrivilegedAction() {
public Object run() {
WebServiceFeature[] features =
new WebServiceFeature[] { securityFeature };
MyWebService myWebService =
myWebServiceService.getMyWebServicePort(features);
// Add your code to call the desired methods.
System.out.println(
myWebService.helloThere("From a Java client"));
return "done";
}
});
}
}
The Explanation
We're applying OWSM client side policy, that requires a SAML Assertion - Bearer and that the request is over SSL. The SSL implementation is the standard J2SE and OWSM uses the JAAS Subject for the identity. The policy is applied via the WebServiceFeature and is described in the OWSM documentation.
Basically, we're using OPSS inside of a J2SE client to establish the JAAS Subject, without providing a password. I used the OPSS documentation as a reference. I used exactly the MyAssertionCallbackHandler from the documentation.
The final "trick" is that the call to the web service is done inside of a call to Subject.doAs(Subejct,PriviledgedAction). This pushes the Subject from the LoginModule on to call stack, and makes it available for the OWSM policy.
The Configuration
So, there a few command line arguments that need to be passed to this client:
-Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=123456
There are the standard J2SE SSL parameters. The JAX-WS client uses the standard SSL.
In my example, I just used the DemoIdentity and DemoTrust, so I set my -D's to
-Djavax.net.ssl.trustStore=C:\\Oracle\\Middleware\\wlserver_10.3\\server\\lib\\DemoTrust.jks -Djavax.net.ssl.trustStorePassword=DemoTrustKeyStorePassPhrase
You also have to pass the program the location of the jps-config.xml.
-Doracle.security.jps.config=c:\jps-config-jse.xml
The jps-config.xml defines the Oracle Platform Security (OPSS) services used by the client. In our use-case, we're going to be using the LoginService to establish an identity for the client. I got the basis of the jps-config-jse.xml from DOMAIN_HOME\config\fmwconfig\jps-config.jse.xml.
At the end of this file, you need to add a jpsContext called Client that contains a reference to the user.assertion.loginmodule
<jpsContext name="Client">
<serviceInstanceRef ref="user.assertion.loginmodule"/>
</jpsContext>
The user assertion login module allows the client to create an identity for the user with no password. It won't work with any username - the user still has to be found in the identity store, which in this case is stored inside of the system-jazn-data.xml. By default, the login module is looking for the system-jazn-data.xml found in the same directory in the jps-config.xml.
I found the system-jazn-data.xml reference useful in building this file:
<jazn-data>
<jazn-realm>
<realm>
<name>jazn.com</name>
<users>
<user>
<name>josh</name>
<guid>1</guid>
</user>
</users>
</realm>
</jazn-realm>
</jazn-data>
The final, configuration step is to make sure that the user that you're asserting - in this case "josh" exists on the server side in WLS. You can just add the user via the WLS admin console.
The Wrap Up
This is definitely a little tricky, but it demonstrates how to use a SAML Bearer assertion. There is no PKI required on the client side - simply the ability to trust the server at the transport level. This is pretty straight forward and simpler then setting-up either sender-vouches or holder-of-key. Consider using this type of approach from within a trusted network.
Thursday, July 9, 2009
OPSS Sample Application
Over the past few weeks, I'd been working with the development team on putting together a nice OPSS Sample Application
The README gives a lot of detail about what the application does and how to use it, so I wanted to spend a little time here to point out some of the ways that existing WLS secured applications can be enhanced with OPSS and also some of the finer points on the application itself.
OPSS provides some good simple user profile services. Admittedly not as elaborate as something like an OIM would provide, but probably cleaner and easier to implement then going through the MBeanReader interfaces of WLS. Also, unlike the MBean interfaces in WLS, there is more than just users and groups. There's user and group attributes. In the sample application this is all very nicely wired to the embedded LDAP that ships with WLS, but through simple configuration can be changed to work with an enterprise repository (LDAP).
In the sample application, there are three enterprise roles - basic user, premium user and ezshareadmin. Notice that the sample application also comes pre-configured with a list of users assigned to those roles. This was all done from JDeveloper and packages as part of the application. When the application is deployed, the information is published into WebLogic Server's authentication provider - the embedded LDAP. For building applications, this can simplify and speed testing. All of the user, group, policy information etc. is stored in the jazn-data.xml, and as I mentioned can be edited from inside of JDeveloper.
In general, I'm not a huge fan of the Java 2 security model, but I think that the way that the CredentialStoreFramework (CSF) uses it in this example is reasonable. Basically, all of the encryption/decryption of the files is done with a symmetric key. Any code that can gain access to that key can access the messages. By using Java 2 permissions model, and having to explicitly grant code access to the key, this restricts the access to only authorized code. This is very useful in centralized environments where many applications are hosted in a single server. In the sample application all of the code is granted access for simplicity, but could be further restricted depending on requirements. This model also breaks the cycle of having to have the password to something...for example, keys are stored in a Java Keystore require a cleartext password to get the private key, but then where do you store that password? Prompt for it at start-up? Java 2 security provides the answer.
I also like the way that the sample application implements accessing the credential store. All of the access is centralized through two methods in the CryptoUtil class. This class can be found in the ezShareModel project. The key thing is that it uses PriviledgedAction to access the store.
This greatly simplifies the configuration of the Java 2 permissions since only the CryptoUtil.class has to be granted access, regardless of whatever other code is in the call stack.
I personally think the coolest part of the sample application is the way that the encryption and decryption is integrated into the ADF View Object. I'm constantly getting questions about data security - mostly around authorization - but this is another key requirement - confidentiality of data on disk. This can be achieved using features of the database, but what this solution shows is a clever way to do it from the middleware. If you look at the BasicFilesView.xml and BasicFilesViewRowImpl.java also in the ezShareModel project, you'll see that the view is using a custom row implementation, and that implementation in-turn is using the CryptoUtil class for all of its encryption/decryption. Very nice!
People can definitely post their questions here about the sample application or maybe suggest some use cases for extending the application....maybe Web Services security...interesting SSO or authorization scenarios. Let me know.
Labels:
opss
Subscribe to:
Posts (Atom)