Jetspeed Proposal: role-based authorization concept LAST MODIFIED: $Date$ AUTHOR: david.taylor@bluesunrise.com STATUS: approved, work in progress for 1.3a2 release ============================ Jetspeed Profiler Proposal ============================ The ProfilerService is a service to abstract the management and mapping of profile resources, also known now as Portal Markup Resources (PSML). The Profiler maps a request for a profile to a profile resource. Since each implementation of a profiler will be different, we are providing the interfaces to the service, and we will also provide a default implementation. The default implementation has a profiling policy defined in this proposal based on resource-specific URLs, Mime-Types and language preferences. More complex implementations will need to use other inputs in mapping to resources such as Cookies, IP Address Ranges, Statistical Resource Usage Analysis, Business Rules inside of servlets or EJBs,... Each ProfilerService will store its profiles in whatever datastore best fits the needs of its application, perhaps in LDAP servers, WebDAV, relational or object databases. The default service persists to the file system, using the existing implementation of PSML files with some changes to the directory layout. The default implementation is meant to be useful for many installations. It also provides base functionality which can be reused or extended by other implementations. The ProfilerService is a Turbine service. =================================== The Default Implementation =================================== The default service uses Turbine Security to control access to user, group and role resources. It makes use of the new Turbine security. The Rundata now has an ACL member, which is used to check for users having access to groups and roles. Optionally, this security checking can be configured to be turned off. The basic mapping provided by the default provider: Resource URL Profile Path ---------------> Request Language Preferences -----------> Profiler ----------> Actual Profile Resource Request Mime Types -------------------> A resource is identified in a request by a Resource URL. This URL is made up of the base part of the URL which addresses the server, along with a Profile Path portion. The profiler looks at the path, which provides addressing for the user, group, role, media type, and localization which is used to map to the actual resource. ---------------------- Capability Map ---------------------- The media type is determined by the CapabilityMap service. The CapabilityMap determines the media type from the HTTP headers. This media type is then passed to the Profiler to be used in mapping the request to a particular PSML resource. The CapabilityMap is planned to eventually support W3 CC/PP RDF descriptions - see http://www.w3.org/TR/NOTE-CCPP/. ---------------------- Users, Groups and Roles ---------------------- Groups allow for resources to be shared by users. A typical use-case is a common portal page for Human Resources. Instead of designing a HR markup for every employee in the company, they only design a markup for the organizations (groups) in the company i.e. Finance, Accounting, Marketing. Secure access to groups and roles is controlled by the ProfilerService. Since Jetspeed does not yet have a security service in place, it is up to the ProfilerService to make use of a security service. The Profiler service queries the security service to verify that a user has access to the group and role resources. The default implementation uses Turbine security. Like groups, roles allow for resources to be shared by users. We are providing support for both roles and groups since some implementations may use group-based security, while others may use role-based security. Groups and role resources may be specified in the resource URL. Alternatively, they can be automatically used when the group or role parameter is not specified. The Profiler will make use of the first matching group or role resource that a user has read access to. ----------------- Resource Names ----------------- The Profiler expects to have a default resource for every user. To use the default resource, you don't need to specify a resource name in the resource URL path. The default resource name is set in the Profiler configuration. In order to specify a resource other than the default markup for a user, resource names are specified in the Resource URL Path. To specify a non-default resource, a resource name must be specified in the path. Resource paths are specified using Turbine parameter pairs. Paths specified in this format are not order specific, but they do expect that every parameter is provided in a name/value consecutive pair in the URL path. To tell Jetspeed that the request is for a specific portal markup resource, use the 'profile' keyword as the name of the parameter, and then the actual resource name is specified in the value portion of the pair. This resource name simply identifies the resource that the user is requesting. An example of a 'BenefitsPage' resource would be: http://host/servlet/jetspeed/profile/BenefitsPage When no name or path is specified, the default resource is used for the current user. The resource name can also have an extension. If it is omitted, the default is to append a configurable extension (PSML). ----------------- Parameters ----------------- Here are the supported parameters in a resource path url: /profile/ - Specifies the name of the profiling resource. /role/ - Specifies that the request can only be satisfied by a common role resource . An example would be /profile/FinancePage/role/Accountant/, meaning that we are requesting the FinancePage resource, and it is the Finance resource for the Accountant role. It will be up to the Profiler implementation to determine if the user is authorized to assume this role. The Security service, whether it is Turbine Security or other, should hold the controlling access information. /group/ - Specifies that the request can only be satisfied by a common group resource. An example would be /group/Finance/profile/BenefitsPage, meaning that we are requesting the BenefitsPage, and it is the Benefits page for the group 'Finance'. It will be up to the Profiler implementation to determine if the user is a member of this group. The Security service, whether it be Turbine Security or other, should hold this mapping. /media-type/ - To specifically request a mediatype in the request. /user/ - Specifies that the request can only be satisfied by a user resource. An example would be /profile/BenefitsPage/user/, meaning that we are requesting the BenefitsPage, but only for the current user. Specifying the name of the user is not allowed, only the authenticated username is applied. This format breaks the rules of Turbine name/value pairs in parameters. Thus, the 'user' keyword must be specified last in the resource path. When no user/group/role parameter is specified, the resource is resolved by first looking for a user resource, then a group resource, and finally a role resource. Only groups and roles that the user has read acess priveleges will be considered. ------------------------------- Localized Resources -------------------------------- Resources can optionally be localized. This is done by suffixing the resource name. The suffix is made up of a required ISO-639 standard two-character language abbreviation, and an optional IS0-3166 standard two-character country code abbreviation. The suffix is of the format: _lc_cc where: lc = language code cc = country code Some examples groups/accounting/html/default_fr_FR.psml // french language, France groups/accounting/html/default_fr.psml // french language, any country For a given locale of fr_FR, the search order for the default accounting resource would be: groups/accounting/html/default_fr_FR.psml groups/accounting/html/default_fr.psml groups/accounting/html/default.psml The profiler will look at the "Content Language" HTML header for locale specific settings. If there are multiple settings, all settings will be searched until the first resource is found. Localization can be configured in the JetspeedResources.properties file. You can configure a default language. This language will be considered the default language and no suffix will be necessary for their resources. # only french belgium profiler.language.default=fr_BE # default language any spanish profiler.language.default=es # all resources must be suffixed profiler.language.default= To turn on/off all localization checking: profiler.default=true/false For a complete list of ISO-639 standard language abbreviations, see: http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt For a complete list of ISO-3166 standard country code abbreviations, see: http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html ------------------------------- Device Explicit Resource Names -------------------------------- Optionally, names can include the media type explicitly. http://host/servlet/jetspeed/profile/BenefitsPage/media-type/html/user/ In this case, the 'media-type' parameter must be specified, and then the actual media type as the parameter value. The above example explicitly asks for the html resource for the BenefitsPage, and explicitly for the current user. First the profiler will look for the media type in the resource name. If it is not specified there, it will then query the CapabilityMap. ------------------------------- Default Media-Type and Fallback -------------------------------- If a request is for a given media type, and the resource is not found for the given media type, then the profiler will fallback to a default resource if available. This default resource is assumed to work for all media types without a specific resource. The default media type resource should be placed in the root directory for a given user, role or group. ------------------------------- Anonymous Access and Profiles -------------------------------- The default resource shown to anonymous logons is configured with profiler.anon.directory setting. A device specific path could be set here, but probably should not so that Jetspeed can autodectect the media type. # Directory used for anonymous access profiler.anon.directory=/user/default/ The actual resource displayed is then dependent on media type, language, and the default resource markup filename. Profiles available to anonymous users are configured with: profiler.anon.profiles=/role/TennisNewUserProfile profiler.anon.profiles=/role/RugbyNewUserProfile profiler.anon.profiles=/role/BadmintonNewUserProfile These are not used directly by the default profiler, but could be used by applications to provide choices of profiles available to anonymous users. The roles must actually have their security setup correctly to work, meaning that access should be given to 'everyone' on these roles. ------------------------------- Authorized Profiles -------------------------------- When a user first signs up, they could be given a choice of profiles available authorized users. This services can be configured as: profiler.authorized.profiles=/role/engineer/ profiler.authorized.profiles=/group/accounting/ -------------------------------- Cookie-based Anonymous Sessions -------------------------------- Cookies are used to automatically remember an unauthorized user's last profile The cookie would remember which 'anon' role it used last. This provides access for unauthorized users to other resources besides the default. -------------------------------- Cookie-based Authorized Sessions -------------------------------- Cookies are used to automatically logon an authorized user and remember the default profile for the authorized user. -------- Profile -------- PSML resource are materialised as a 'Profile' object. It would be interesting if the Profile's contents (Controls, Controllers, Portlets) were also first-class persistence-capable objects, so that Customizers could store changes to one portlet ref instead of re-writing the entire psml tree. At this point in time, the Profile will simply be a wrapper around the existing implementation along with some new accessors. ----------------------------------- Jetspeed Resources Configuration ----------------------------------- # The Profiler Service is implemented as a Turbine service. services.Profiler.classname=org.apache.jetspeed.services.profiler.JetspeedProfilerService # The webapp relative path to the root profiling directory services.Profiler.root=/profiles/ # The webapp relative path to directory used for anonymous access services.Profiler.anon.dir=/profiles/user/default/ # The default resource filename services.Profiler.resource.default=default # The default resource filename extension services.Profiler.resource.ext=psml # Use security? services.Profiler.security=false # language configuration services.Profiler.language=false # ex: only french belgium #services.Profiler.language.default=fr_BE # ex: default language any spanish #services.Profiler.language.default=es # default: all resources must be suffixed services.Profiler.language.default= # anonymous profile list services.Profiler.profiles.anon= # authorized profile list services.Profiler.profiles.authorized= ---------------- Directory Layout ----------------- All resources are defined as relative to the root (profiler.base.url). Markup files are organized in directories under the root. There are three subpaths under the root: Root | --- / user | --- / role | --- / group Under the /user subtree, are the directories for all users and likewise for roles and groups: user | --- / raul | --- / steve | --- / luis role | --- / engineer | --- / accountant | --- / supervisor group | --- / finance | --- / marketing | --- / accounting Under each of these subtrees, there is one directory for each media type. Media types are capable of supporting one or more mime types. For instance, both "text/html" and "text/dhtml" could map to the the same media type. But they also may not. This mapping is controlled in the Portlet Registry (JetspeedConfig.jcfg) with the CapabilityMapRegistry. In the example below, both mime types map to the same media type. text/html text/dhtml Media types are defined in the media type registry. HTML ---------- Examples ---------- Here is an example tree: {root} users {default} default.psml // fallback: can be used as crossdevice media html default.psml raul html default.psml page1.psml wml default.psml steve default.psml // fallback: can be used as crossdevice media html default.psml groups accounting html default.psml page1.psml wml default.psml marketing html default.psml An incoming request from an html browser of: http://server/servlet/jetspeed would map to the resource path: {root}/user/{current-user}/html/default.psml An incoming request from an html browser of: http://server/servlet/jetspeed/group/sales/profile/SalesCenter would map to the resource path: {root}/group/sales/html/SalesCenter.psml An incoming request from a wml browser of: http://server/servlet/jetspeed/profile/JavaCenter/role/programmer/ would map to the resource path: {root}/role/programmer/wml/JavaCenter.psml An incoming request from a wml browser of for user 'raul': http://server/servlet/jetspeed/profile/MySportsPortal would map to the resource path: {root}/user/raul/wml/MySportsPage.psml and if that failed, it would try again for the user's groups and roles. it may find a page such as: {root}/role/footballfan/wml/MySportsPage.psml ------------------------- Modifications to the Code ------------------------- The JetspeedProfilerService will be implemented in the org.apache.jetspeed.services.profiler package. The ProfilerService interface will be placed in the org.apache.jetspeed.services.profiler package. The Profile interface will be place in the org.apache.jetspeed.om.profiler The JetspeedProfile class will be implemented and placed in the org.apache.jetspeed.om.profiler package The interception of requests will only occur in org.apache.jetspeed.turbine.screens.Home.java Home.java will need to be modified. This is under the assumption that there is only one entry point into Jetspeed markup generation. The package org.apache.jetspeed.profiler will be removed. All import statements to this package will be replaced with imports to the service. A few new string resources will be adaded to JetspeedResources.java ------------------------------ Modifications to Configuration ------------------------------ The Profile Registry in the jcfg file would be removed. The 'psml' directory will be removed. A new directory under 'content' will be added, 'profiles'. It will have the structure as shown in the default implementation above. The JetspeedResources.Properties will be modified to add the configuration settings described above. Add the profiler service to the TurbineResources.Properties. ==================== Interfaces ==================== All profiler services must implement the ProfilerService interface. The Profile interface defines a profile instance. A Profile is the object representation of a Jetspeed PSML resource. public interface ProfilerService extends Service { /** The name of this service */ public String SERVICE_NAME = "ProfileManager"; /* * get the Profile object using the Rundata state and capability map * this is the mapping functionality of the profiler * * @param rundata the rundata object for the current request * @return a Profile object if found by the manager or null */ public Profile getProfile(RunData rundata); /* * stores a cookie in response to the current resource * * @param rundata the rundata object for the current request */ public void storeCookie(RunData rundata); } public interface Profile extends Initable { /** Gets the root set of portlets for this profile object. @return The root portlet set for this profile. */ public PortletSet getRootSet(); /** Gets the PortletSetFactory for this profile @return The portlet set factory for this profile. */ public PortletSetFactory getFactory(); /** stores the resource by merging and rewriting the psml file @throws ProfileException if an error occurs storing the profile */ public void store() throws ProfileException; } ------------------------------------------ Jetspeed Default Implementation Accessors: ------------------------------------------ class JetspeedProfile { /* accessors */ String getUser(); String getGroup(); String getRole(); String getResourceName(); String getResourcePath(); String getMediaType(); String getLanguageCode(); String getCountryCode(); } class JetspeedProfilerService { /* get the base URL for the profile registry */ String getBaseURL(); /* get the default resource name */ String getDefaultResourceName(); /* is security enabled */ boolean isSecurityEnabled(); getAuthorizedProfiles(); getAnonymousProfiles(); } ============================== Future Directions ============================== - Mapping IP address ranges to Groups. This would require a table, either in the database or a simple text file. - Dynamic profiling based on usage statistics - The Profile's content generation based on runtime criteria, not static psml files