Release notes + maven site. On Mon, Nov 23, 2009 at 8:53 PM, Ulrich Stärk <[email protected]> wrote:
> This will break all applications using chenillekit until the chenillekit > devs update their code and should be visibly documented somewhere. > > Uli > > Howard Lewis Ship schrieb: > > Good catch, and I agree. >> >> On Mon, Nov 23, 2009 at 10:07 AM, Igor Drobiazko >> <[email protected]> wrote: >> >>> I think the contribution "^org/chenillekit/tapestry/" should be removed >>> from >>> the configuration of the RegexpAuthorizer. App developers using >>> Chenillekit >>> should contribute it. >>> >>> On Mon, Nov 9, 2009 at 6:23 PM, <[email protected]> wrote: >>> >>> Author: robertdzeigler >>>> Date: Mon Nov 9 17:23:10 2009 >>>> New Revision: 834151 >>>> >>>> URL: http://svn.apache.org/viewvc?rev=834151&view=rev >>>> Log: >>>> TAP5-815: Asset dispatcher allows any file inside the webapp visible and >>>> downloadable (5.2 branch) >>>> >>>> Added: >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcher.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RegexAuthorizer.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/WhitelistAuthorizer.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathAuthorizer.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcherTest.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RegexAuthorizerTest.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/WhitelistAuthorizerTest.java >>>> Modified: >>>> tapestry/tapestry5/trunk/src/site/apt/guide/assets.apt >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java >>>> >>>> >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java >>>> >>>> Modified: tapestry/tapestry5/trunk/src/site/apt/guide/assets.apt >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/guide/assets.apt?rev=834151&r1=834150&r2=834151&view=diff >>>> >>>> >>>> ============================================================================== >>>> --- tapestry/tapestry5/trunk/src/site/apt/guide/assets.apt (original) >>>> +++ tapestry/tapestry5/trunk/src/site/apt/guide/assets.apt Mon Nov 9 >>>> 17:23:10 2009 >>>> @@ -138,6 +138,31 @@ >>>> In addition, context assets will use the URL prefix >>>> <<</assets/ctx/>>><app-version><<</>>>. >>>> >>>> >>>> +Securing Assets >>>> + >>>> + Securing assets is an important consideration for any web >>>> application. >>>> Many assets, such as hibernate configuration >>>> + files, sit in the classpath and are exposable via the Asset service, >>>> which is not desirable. To protect these and >>>> + other sensitive assets, Tapestry provides the >>>> AssetProtectionDispatcher. >>>> This dispatcher sits in front of the >>>> + AssetDispatcher, the service responsible for streaming assets to the >>>> client, and watches for Asset requests. >>>> + When an asset request comes in, the protection dispatcher checks for >>>> authorization to view the file against a >>>> + contributed list of AssetPathAuthorizer implementations. >>>> Determination >>>> of whether the client can view the requested >>>> + resource is then made based on whether any of the contributed >>>> AssetPathAuthorizer implementations explicitly allowed >>>> + or denied access to the resource. >>>> + >>>> + Tapestry provides two AssetPathAuthorizer implemenations "out of the >>>> box" to which users may contribute: RegexAuthorizer >>>> + and WhitelistAuthorizer. RegexAuthorizer uses regular expressions to >>>> determine assets which are viewable by the >>>> + client; any assets that match one of its (contributed) regular >>>> expressions are authorized. Anything not matched is >>>> + passed through to the WhitelistAuthorizer. WhitelistAuthorizer uses >>>> an >>>> exact-matching whitelist. Anything matching >>>> + exactly one its contributions is allowed; all other asset requests >>>> are >>>> denied. The default tapestry configuration >>>> + contributes nothing to WhitelistAuthorizer (access will be denied to >>>> all >>>> asset requests passed through to it), and >>>> + explicitly allows access to css, jpg, jpeg, js, png, and gif files >>>> associated with tapestry (tapestry.js, blackbird >>>> + files, date picker files, etc.). The default contribution also >>>> enables >>>> access to the css, jpg, jpeg, js, png, and gif >>>> + files provided by the popular chenille-kit 3rd party library. The >>>> default configuration denies access to all other >>>> + assets. To enable access to your application's assets, either >>>> contribute a custom AssetPathAnalyzer, or contribute >>>> + appropriate regular expression or exact path contributions to >>>> RegexAuthorizer or WhitelistAuthorizer, respectively. >>>> + See TapestryModule.contribteRegexAuthorizer for examples. >>>> + >>>> + >>>> Performance Notes >>>> >>>> Assets are expected to be entirely static (not changing while the >>>> application is deployed). When Tapestry generates a URL >>>> @@ -146,4 +171,4 @@ >>>> asset. >>>> >>>> In addition, Tapestry will {{{compress.html}GZIP compress}} the content >>>> of <all> assets (if the asset >>>> - is compressable, and the client supports it). >>>> \ No newline at end of file >>>> + is compressable, and the client supports it). >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcher.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcher.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcher.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcher.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,92 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +package org.apache.tapestry5.internal.services; >>>> + >>>> +import java.io.IOException; >>>> +import java.util.Collection; >>>> +import java.util.Collections; >>>> +import java.util.List; >>>> + >>>> +import javax.servlet.http.HttpServletResponse; >>>> + >>>> +import org.apache.tapestry5.internal.services.RequestConstants; >>>> +import org.apache.tapestry5.services.*; >>>> +import org.slf4j.Logger; >>>> + >>>> +/** >>>> + * Dispatcher that handles whether to allow or deny access to >>>> particular >>>> + * assets. Actual work of authorizing a particular url is handled by >>>> + * implementations of AssetPathAuthorizer. Configuration is an ordered >>>> + * list of AssetPathAuthorizers. Each authorizer specifies an order of >>>> + * operations as a list (see AssetPathAuthorizer.Order). >>>> + * >>>> + */ >>>> +public class AssetProtectionDispatcher implements Dispatcher >>>> +{ >>>> + >>>> + private final Collection<AssetPathAuthorizer> authorizers; >>>> + private final ClasspathAssetAliasManager assetAliasManager; >>>> + private final Logger logger; >>>> + >>>> + public AssetProtectionDispatcher( >>>> + List<AssetPathAuthorizer> auths, >>>> + ClasspathAssetAliasManager manager, >>>> + Logger logger) >>>> + { >>>> + this.authorizers = Collections.unmodifiableList(auths); >>>> + this.assetAliasManager = manager; >>>> + this.logger = logger; >>>> + } >>>> + >>>> + public boolean dispatch(Request request, Response response) >>>> + throws IOException >>>> + { >>>> + String path = request.getPath(); >>>> + //we only protect assets, and don't examine any other url's. >>>> + if (!path.startsWith(RequestConstants.ASSET_PATH_PREFIX)) >>>> + { >>>> + return false; >>>> + } >>>> + String resourcePath = assetAliasManager.toResourcePath(path); >>>> + for(AssetPathAuthorizer auth : authorizers) >>>> + { >>>> + for(AssetPathAuthorizer.Order o : auth.order()) >>>> + { >>>> + if (o == AssetPathAuthorizer.Order.ALLOW) >>>> + { >>>> + if (auth.accessAllowed(resourcePath)) >>>> + { >>>> + logger.debug("Allowing access to " + >>>> resourcePath); >>>> + return false; >>>> + } >>>> + } >>>> + else >>>> + { >>>> + if (auth.accessDenied(resourcePath)) >>>> + { >>>> + logger.debug("Denying access to " + >>>> resourcePath); >>>> + >>>> response.sendError(HttpServletResponse.SC_FORBIDDEN,resourcePath); >>>> + return true; >>>> + } >>>> + } >>>> + } >>>> + } >>>> + //if we get here, no Authorizer had anything useful to say >>>> about >>>> the resourcePath. >>>> + //so let it fall through. >>>> + logger.debug("Fell through the list of authorizers. Allowing >>>> access to: " + resourcePath); >>>> + return false; >>>> + } >>>> + >>>> +} >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RegexAuthorizer.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RegexAuthorizer.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RegexAuthorizer.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RegexAuthorizer.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,76 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +package org.apache.tapestry5.internal.services; >>>> + >>>> +import org.apache.tapestry5.services.AssetPathAuthorizer; >>>> + >>>> +import java.util.ArrayList; >>>> +import java.util.Arrays; >>>> +import java.util.Collection; >>>> +import java.util.Collections; >>>> +import java.util.List; >>>> +import java.util.regex.Pattern; >>>> + >>>> +/** >>>> + * Provides a regex-based authorization scheme for asset-access >>>> authorization. >>>> + * Note that this implementation doesn't actually deny access to >>>> anything. >>>> + * But it's placement within the chain of command of authorizers is >>>> just >>>> before >>>> + * the whitelist authorizer, which has an explicit deny policy. >>>> + * Hence, as long as the whitelist authorizer is being used in >>>> conjunction >>>> with >>>> + * the regex authorizer, there is no need to worry about accessDenied >>>> in >>>> this authorizer. >>>> + * >>>> + */ >>>> +public class RegexAuthorizer implements AssetPathAuthorizer >>>> +{ >>>> + >>>> + private final Collection<Pattern> _regexes; >>>> + >>>> + public RegexAuthorizer(final Collection<String> regex) >>>> + { >>>> + //an alternate way to construct this would be to make sure that >>>> each pattern is grouped >>>> + //and then to regex or the various patterns together into a >>>> single >>>> pattern. >>>> + //that might be faster, but probably not enough to make a >>>> difference, and this is cleaner. >>>> + List<Pattern> tmp = new ArrayList<Pattern>(); >>>> + for(String exp : regex) >>>> + { >>>> + tmp.add(Pattern.compile(exp)); >>>> + } >>>> + _regexes = Collections.unmodifiableCollection(tmp); >>>> + >>>> + } >>>> + >>>> + public boolean accessAllowed(String resourcePath) >>>> + { >>>> + for(Pattern regex : _regexes) >>>> + { >>>> + if (regex.matcher(resourcePath).matches()) >>>> + { >>>> + return true; >>>> + } >>>> + } >>>> + return false; >>>> + } >>>> + >>>> + public boolean accessDenied(String resourcePath) >>>> + { >>>> + return false; >>>> + } >>>> + >>>> + public List<Order> order() >>>> + { >>>> + return Arrays.asList(Order.ALLOW); >>>> + } >>>> + >>>> +} >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/WhitelistAuthorizer.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/WhitelistAuthorizer.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/WhitelistAuthorizer.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/WhitelistAuthorizer.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,59 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +package org.apache.tapestry5.internal.services; >>>> + >>>> +import org.apache.tapestry5.services.AssetPathAuthorizer; >>>> + >>>> +import java.util.Arrays; >>>> +import java.util.Collection; >>>> +import java.util.List; >>>> +import java.util.Map; >>>> +import java.util.concurrent.ConcurrentHashMap; >>>> + >>>> +/** >>>> + * AssetPathAuthorizer that determines access rights based on exact >>>> matching to a contributed whitelist. >>>> + * Any resource not explicitly specified in the whitelist is denied >>>> access. >>>> + */ >>>> +public class WhitelistAuthorizer implements AssetPathAuthorizer >>>> +{ >>>> + >>>> + public List<Order> order() >>>> + { >>>> + return Arrays.asList(Order.ALLOW, Order.DENY); >>>> + } >>>> + >>>> + //hash the resource paths for fast lookups. >>>> + private final Map<String, Boolean> _paths; >>>> + >>>> + public WhitelistAuthorizer(Collection<String> paths) >>>> + { >>>> + _paths = new ConcurrentHashMap<String, Boolean>(); >>>> + for(String path : paths) >>>> + { >>>> + _paths.put(path, true); >>>> + } >>>> + } >>>> + >>>> + public boolean accessAllowed(String resourcePath) >>>> + { >>>> + return (_paths.containsKey(resourcePath)); >>>> + } >>>> + >>>> + public boolean accessDenied(String resourcePath) >>>> + { >>>> + return !_paths.containsKey(resourcePath); >>>> + } >>>> + >>>> +} >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathAuthorizer.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathAuthorizer.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathAuthorizer.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathAuthorizer.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,76 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +package org.apache.tapestry5.services; >>>> + >>>> +import java.util.List; >>>> + >>>> +/** >>>> + * Determines whether access to an asset is allowed, denied, or >>>> undetermined. >>>> + * Each contributed authorizer makes up part of a chain of command for >>>> determining access. >>>> + * Access is explicitly allowed if accessAllowed returns true. >>>> + * Access is explicitly denied if accessDenied returns true. >>>> + * Ordering depends on the order specified by the "order" parameter. >>>> + * Hence, an implementation which specifies an order of: >>>> + * ALLOW, DENY, and returns true from both accessAllowed and >>>> accessDenied >>>> + * will allow access for all resources. With the same return values for >>>> the >>>> + * access* methods but the order switched to DENY, ALLOW, access to all >>>> resources >>>> + * would be denied. It is possible for an authorizer to have "nothing >>>> + * to say" regarding a particular resource. If accessAllowed returns >>>> false, >>>> + * it does not mean that access is denied, merely that it is not >>>> explicitly allowed. >>>> + * If accessDenied returns false, it does not mean that access is >>>> allowed, >>>> merely that >>>> + * it is not explicitly denied. Hence, if both accessAllowed and >>>> accessDenied return false, >>>> + * control will pass to the next authorizer in the chain. >>>> + * >>>> + */ >>>> +public interface AssetPathAuthorizer >>>> +{ >>>> + >>>> + /** >>>> + * Types of orderings, either ALLOW or DENY. >>>> + */ >>>> + enum Order {ALLOW, DENY;} >>>> + >>>> + /** >>>> + * Specify the ordering for this authorizer. >>>> + * @return the operations for this authorizer. >>>> + * Operations will be performed in the order returned by the >>>> iterator. >>>> + * It is assumed that the authorizer correctly implements each form >>>> of >>>> + * ordering returned. It is acceptable to only return only ALLOW or >>>> DENY. >>>> + */ >>>> + List<Order> order(); >>>> + >>>> + /** >>>> + * Determines whether a request to "resourcePath" is allowed. >>>> + * @param resourcePath >>>> + * @return true if access is explicitly allowed for the path. False >>>> otherwise. >>>> + * For example, a whitelist implementation would return true if the >>>> resource >>>> + * was listed, and false otherwise. A blacklist implementation >>>> would >>>> return >>>> + * false regardless of whether the path was in the blacklist. >>>> + * Alternatively, if the blacklist specified an order of DENY, >>>> ALLOW, >>>> it could >>>> + * return true from accessAllowed if the resource was not >>>> explicitly >>>> listed in its >>>> + * blacklist. >>>> + */ >>>> + boolean accessAllowed(String resourcePath); >>>> + >>>> + /** >>>> + * >>>> + * @param resourcePath >>>> + * @return true if access is explicitly prohibited for the path. >>>> False >>>> otherwise. >>>> + * For example, a whitelist implementation would return true if the >>>> resource was >>>> + * not explicitly listed, and false otherwise. A blacklist >>>> implementation would >>>> + * return true if the resource was explicitly denied, and false >>>> otherwise. >>>> + */ >>>> + boolean accessDenied(String resourcePath); >>>> +} >>>> >>>> Modified: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=834151&r1=834150&r2=834151&view=diff >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java >>>> (original) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -305,6 +305,9 @@ >>>> binder.bind(PageRenderLinkSource.class, >>>> PageRenderLinkSourceImpl.class); >>>> binder.bind(ClientInfrastructure.class, >>>> ClientInfrastructureImpl.class); >>>> binder.bind(URLRewriter.class, URLRewriterImpl.class); >>>> + binder.bind(Dispatcher.class, >>>> AssetProtectionDispatcher.class).withId("AssetProtectionDispatcher"); >>>> + binder.bind(AssetPathAuthorizer.class, >>>> WhitelistAuthorizer.class).withId("WhitelistAuthorizer"); >>>> + binder.bind(AssetPathAuthorizer.class, >>>> RegexAuthorizer.class).withId("RegexAuthorizer"); >>>> } >>>> >>>> // >>>> ======================================================================== >>>> @@ -1572,13 +1575,17 @@ >>>> * and forwards onto {...@link PageRenderRequestHandler}</dd> >>>> <dt>ComponentEvent</dt> <dd>Identifies the {...@link >>>> * ComponentEventRequestParameters} and forwards onto the {...@link >>>> ComponentEventRequestHandler}</dd> </dl> >>>> */ >>>> - public static void >>>> contributeMasterDispatcher(OrderedConfiguration<Dispatcher> >>>> configuration) >>>> + public static void >>>> contributeMasterDispatcher(OrderedConfiguration<Dispatcher> >>>> configuration, >>>> + >>>> @InjectService("AssetProtectionDispatcher") Dispatcher assetProt) >>>> { >>>> // Looks for the root path and renders the start page. This is >>>> maintained for compatibility >>>> // with earlier versions of Tapestry 5, it is recommended that an >>>> Index page be used instead. >>>> >>>> configuration.addInstance("RootPath", RootPathDispatcher.class, >>>> "before:Asset"); >>>> >>>> + //this goes before asset to make sure that only allowed assets >>>> are >>>> streamed to the client. >>>> + configuration.add("AssetProtection", assetProt, >>>> "before:Asset"); >>>> + >>>> // This goes first because an asset to be streamed may have an >>>> file >>>> extension, such as >>>> // ".html", that will confuse the later dispatchers. >>>> >>>> @@ -1591,6 +1598,7 @@ >>>> configuration.addInstance("PageRender", >>>> PageRenderDispatcher.class); >>>> } >>>> >>>> + >>>> /** >>>> * Contributes a default object renderer for type Object, plus >>>> specialized renderers for {...@link >>>> * org.apache.tapestry5.services.Request}, {...@link >>>> org.apache.tapestry5.ioc.Location}, {...@link >>>> @@ -2480,4 +2488,41 @@ >>>> }; >>>> } >>>> >>>> + /** >>>> + * Contributes the default set of AssetPathAuthorizers into the >>>> AssetProtectionDispatcher. >>>> + * @param whitelist authorization based on explicit whitelisting. >>>> + * @param regex authorization based on pattern matching. >>>> + * @param conf >>>> + */ >>>> + public static void contributeAssetProtectionDispatcher( >>>> + @InjectService("WhitelistAuthorizer") AssetPathAuthorizer >>>> whitelist, >>>> + @InjectService("RegexAuthorizer") AssetPathAuthorizer >>>> regex, >>>> + OrderedConfiguration<AssetPathAuthorizer> conf) >>>> + { >>>> + //putting whitelist after everything ensures that, in fact, >>>> nothing falls through. >>>> + //also ensures that whitelist gives other authorizers the >>>> chance >>>> to act... >>>> + conf.add("regex",regex,"before:whitelist"); >>>> + conf.add("whitelist", whitelist,"after:*"); >>>> + } >>>> + >>>> + public void contributeRegexAuthorizer(Configuration<String> regex, >>>> + @Symbol("tapestry.scriptaculous.path") String >>>> scriptPath, >>>> + @Symbol("tapestry.blackbird.path") String >>>> blackbirdPath, >>>> + @Symbol("tapestry.datepicker.path") String >>>> datepickerPath) >>>> + { >>>> + //allow any js, jpg, jpeg, png, or css under >>>> org/chenillekit/tapstry. The funky bit of ([^/.]+/)* is what allows >>>> + //multiple paths, while not allowing any of those paths to >>>> contains ./ or ../ thereby preventing paths like: >>>> + //org/chenillekit/tapestry/../../../foo.js >>>> + String pathPattern = >>>> "([^/.]+/)*[^/.]+\\.((css)|(js)|(jpg)|(jpeg)|(png)|(gif))$"; >>>> + regex.add("^org/chenillekit/tapestry/" + pathPattern); >>>> + >>>> + regex.add("^org/apache/tapestry5/" + pathPattern); >>>> + >>>> + regex.add(blackbirdPath + "/" + pathPattern); >>>> + regex.add(datepickerPath + "/" + pathPattern); >>>> + regex.add(scriptPath + "/" + pathPattern); >>>> + //allow access to virtual assets. Critical for >>>> tapestry-combined >>>> js files. >>>> + regex.add("virtual/" + pathPattern); >>>> + } >>>> + >>>> } >>>> >>>> Modified: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java?rev=834151&r1=834150&r2=834151&view=diff >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java >>>> (original) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -257,4 +257,22 @@ >>>> { >>>> configuration.add("ReverseStringsWorker", new >>>> ReverseStringsWorker()); >>>> } >>>> + >>>> + public static void contributeRegexAuthorizer(Configuration<String> >>>> configuration) { >>>> + //use this rather than a blanket regex (^.*.jpg$, etc.); want >>>> to >>>> be sure that tests pass from the default >>>> + //configuration setup, (eg: this way, I realized that the >>>> "virtual" assets folder >>>> + //needed to be opened up in the tapestry-provided >>>> contributions) >>>> rather than from some blanket configuration in the appmodule >>>> + //opening up all css, js, etc. files. >>>> + //would contribute to whitelist except that the resource path >>>> between ctxt and the rest of the path can change. >>>> + configuration.add("^ctx/[^/]+/css/app\\.css$"); >>>> + configuration.add("^ctx/[^/]+/layout/style\\.css$"); >>>> + configuration.add("^ctx/[^/]+/layout/images/bg\\.gif$"); >>>> + configuration.add("^ctx/[^/]+/layout/images/header\\.gif$"); >>>> + >>>> configuration.add("^ctx/[^/]+/layout/images/rightsmall\\.gif$"); >>>> + configuration.add("^ctx/[^/]+/layout/images/rightbig\\.gif$"); >>>> + configuration.add("^ctx/[^/]+/layout/images/bottom\\.gif$"); >>>> + configuration.add("^ctx/[^/]+/layout/images/footer\\.gif$"); >>>> + configuration.add("^ctx/[^/]+/images/tapestry_banner\\.gif$"); >>>> + configuration.add("^ctx/[^/]+/images/asf_logo_wide\\.gif$"); >>>> + } >>>> } >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcherTest.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcherTest.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcherTest.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/AssetProtectionDispatcherTest.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,92 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +package org.apache.tapestry5.internal.services; >>>> + >>>> +import static org.easymock.EasyMock.createMock; >>>> +import static org.easymock.EasyMock.expect; >>>> +import static org.easymock.EasyMock.*; >>>> + >>>> +import java.io.IOException; >>>> +import java.util.ArrayList; >>>> +import java.util.Arrays; >>>> +import java.util.Collections; >>>> +import java.util.List; >>>> + >>>> +import javax.servlet.http.HttpServletResponse; >>>> + >>>> +import org.apache.tapestry5.internal.services.RequestConstants; >>>> +import >>>> org.apache.tapestry5.internal.services.AssetProtectionDispatcher; >>>> +import org.apache.tapestry5.services.ClasspathAssetAliasManager; >>>> +import org.apache.tapestry5.services.Request; >>>> +import org.apache.tapestry5.services.Response; >>>> +import org.apache.tapestry5.services.AssetPathAuthorizer; >>>> +import org.testng.Assert; >>>> +import org.testng.annotations.Test; >>>> +import org.slf4j.Logger; >>>> + >>>> +public class AssetProtectionDispatcherTest extends Assert >>>> +{ >>>> + >>>> + @Test >>>> + public void ignores_nonassets() throws IOException >>>> + { >>>> + //shouldn't need any configuration here... >>>> + List<AssetPathAuthorizer> auths = Collections.emptyList(); >>>> + Logger logger = createMock(Logger.class); >>>> + AssetProtectionDispatcher disp = new >>>> AssetProtectionDispatcher(auths,null,logger); >>>> + Request request = createMock(Request.class); >>>> + expect(request.getPath()).andReturn("start"); >>>> + Response response = createMock(Response.class); >>>> + replay(request,response,logger); >>>> + assertFalse(disp.dispatch(request, response)); >>>> + verify(request,response,logger); >>>> + } >>>> + >>>> + @Test >>>> + public void checks_authorizers() throws IOException >>>> + { >>>> + Logger logger = createMock(Logger.class); >>>> + List<AssetPathAuthorizer> auths = new >>>> ArrayList<AssetPathAuthorizer>(); >>>> + AssetPathAuthorizer auth = >>>> createMock(AssetPathAuthorizer.class); >>>> + >>>> + >>>> >>>> >>>> expect(auth.order()).andReturn(Arrays.asList(AssetPathAuthorizer.Order.ALLOW, >>>> AssetPathAuthorizer.Order.DENY)).times(2); >>>> + >>>> + expect(auth.accessAllowed("/cayenne.xml")).andReturn(false); >>>> + expect(auth.accessDenied("/cayenne.xml")).andReturn(true); >>>> + >>>> >>>> >>>> expect(auth.accessAllowed("/org/apache/tapestry/default.css")).andReturn(true); >>>> + auths.add(auth); >>>> + >>>> + logger.debug("Denying access to /cayenne.xml"); >>>> + logger.debug("Allowing access to >>>> /org/apache/tapestry/default.css"); >>>> + >>>> + Request request = createMock(Request.class); >>>> + Response response = createMock(Response.class); >>>> + >>>> expect(request.getPath()).andReturn(RequestConstants.ASSET_PATH_PREFIX >>>> + >>>> "/cayenne.xml"); >>>> + >>>> expect(request.getPath()).andReturn(RequestConstants.ASSET_PATH_PREFIX >>>> + >>>> "/org/apache/tapestry/default.css"); >>>> + response.sendError(HttpServletResponse.SC_FORBIDDEN, >>>> "/cayenne.xml"); >>>> + >>>> + ClasspathAssetAliasManager manager = >>>> createMock(ClasspathAssetAliasManager.class); >>>> + >>>> expect(manager.toResourcePath(RequestConstants.ASSET_PATH_PREFIX + >>>> "/cayenne.xml")).andReturn("/cayenne.xml"); >>>> + expect(manager.toResourcePath( >>>> + RequestConstants.ASSET_PATH_PREFIX + >>>> "/org/apache/tapestry/default.css")) >>>> + .andReturn("/org/apache/tapestry/default.css"); >>>> + replay(auth,request,response,manager,logger); >>>> + AssetProtectionDispatcher disp = new >>>> AssetProtectionDispatcher(auths,manager,logger); >>>> + >>>> + assertTrue(disp.dispatch(request,response)); >>>> + assertFalse(disp.dispatch(request, response)); >>>> + verify(auth,request,response,logger); >>>> + } >>>> +} >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RegexAuthorizerTest.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RegexAuthorizerTest.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RegexAuthorizerTest.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RegexAuthorizerTest.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,53 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +package org.apache.tapestry5.internal.services; >>>> + >>>> +import java.util.Arrays; >>>> +import java.util.List; >>>> + >>>> +import org.testng.Assert; >>>> +import org.testng.annotations.Test; >>>> +import org.apache.tapestry5.internal.services.RegexAuthorizer; >>>> + >>>> +public class RegexAuthorizerTest extends Assert >>>> +{ >>>> + >>>> + @Test >>>> + public void test_regexes() >>>> + { >>>> + List<String> patterns = >>>> Arrays.asList("^.*\\.png$","^.*\\.jpg","^.*\\.jpeg"); >>>> + RegexAuthorizer auth = new RegexAuthorizer(patterns); >>>> + String pkg = "assets/com/saiwaisolutions/resources/"; >>>> + String png = pkg + "foo.png"; >>>> + String jpg = pkg + "foo.jpg"; >>>> + String jpeg = pkg + "foo.jpeg"; >>>> + String xml = pkg + "foo.xml"; >>>> + test(auth,png,true); >>>> + test(auth,jpg,true); >>>> + test(auth,jpeg,true); >>>> + test(auth,xml,false); >>>> + } >>>> + >>>> + private static void test(RegexAuthorizer auth, String one,boolean >>>> allowed) >>>> + { >>>> + assertEquals(auth.accessAllowed(one),allowed); >>>> + assertEquals( >>>> + auth.accessAllowed( >>>> + "http://localhost:8080" + one), >>>> + allowed); >>>> + assertFalse(auth.accessDenied(one)); >>>> + assertFalse(auth.accessDenied("http://localhost:8080" + one)); >>>> + } >>>> +} >>>> >>>> Added: >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/WhitelistAuthorizerTest.java >>>> URL: >>>> >>>> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/WhitelistAuthorizerTest.java?rev=834151&view=auto >>>> >>>> >>>> ============================================================================== >>>> --- >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/WhitelistAuthorizerTest.java >>>> (added) >>>> +++ >>>> >>>> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/WhitelistAuthorizerTest.java >>>> Mon Nov 9 17:23:10 2009 >>>> @@ -0,0 +1,45 @@ >>>> +// Copyright 2009 The Apache Software Foundation >>>> +// >>>> +// Licensed under the Apache License, Version 2.0 (the "License"); >>>> +// you may not use this file except in compliance with the License. >>>> +// You may obtain a copy of the License at >>>> +// >>>> +// http://www.apache.org/licenses/LICENSE-2.0 >>>> +// >>>> +// Unless required by applicable law or agreed to in writing, software >>>> +// distributed under the License is distributed on an "AS IS" BASIS, >>>> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >>>> implied. >>>> +// See the License for the specific language governing permissions and >>>> +// limitations under the License. >>>> + >>>> +/* >>>> + * Created on Jul 28, 2007 >>>> + * >>>> + * >>>> + */ >>>> +package org.apache.tapestry5.internal.services; >>>> + >>>> +import java.util.Arrays; >>>> + >>>> +import org.testng.Assert; >>>> +import org.testng.annotations.Test; >>>> +import org.apache.tapestry5.internal.services.WhitelistAuthorizer; >>>> +import org.apache.tapestry5.services.AssetPathAuthorizer; >>>> + >>>> +public class WhitelistAuthorizerTest extends Assert { >>>> + >>>> + @Test >>>> + public void run() >>>> + { >>>> + WhitelistAuthorizer auth = new >>>> WhitelistAuthorizer(Arrays.asList("foo")); >>>> + assertEquals(auth.order().get(0), >>>> AssetPathAuthorizer.Order.ALLOW); >>>> + assertEquals(auth.order().get(1), >>>> AssetPathAuthorizer.Order.DENY); >>>> + assertEquals(auth.order().size(),2); >>>> + assertTrue(auth.accessAllowed("foo")); >>>> + assertFalse(auth.accessDenied("foo")); >>>> + >>>> + assertFalse(auth.accessAllowed("bar")); >>>> + assertTrue(auth.accessDenied("bar")); >>>> + } >>>> + >>>> +} >>>> >>>> >>>> >>>> >>> -- >>> Best regards, >>> >>> Igor Drobiazko >>> >>> >> >> >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > > -- Best regards, Igor Drobiazko
