Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignored Resources Policy #44

Merged
merged 18 commits into from
Dec 19, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions distro/data/src/main/resources/data/all-policyDefs.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,17 @@
"template" : "Consumers are limited to @{limit} requests per @{granularity} per @{period}."
}
]
},
{
"name" : "Ignored Resources Policy",
"description" : "Requests satisfying the provided regular expression will be ignored.",
"policyImpl" : "class:io.apiman.gateway.engine.policies.IgnoredResourcesPolicy",
"icon" : "eye-slash",
"templates" : [
{
"language" : null,
"template" : "Requests matching any of the @{pathsToIgnore.size()} regular expressions provided will receive a 404 error code."
}
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum PolicyFailureType {

Authentication,
Authorization,
NotFound,
Other

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2014 JBoss Inc
*
* 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 io.apiman.gateway.engine.policies;

import io.apiman.gateway.engine.beans.PolicyFailure;
import io.apiman.gateway.engine.beans.PolicyFailureType;
import io.apiman.gateway.engine.beans.ServiceRequest;
import io.apiman.gateway.engine.components.IPolicyFailureFactoryComponent;
import io.apiman.gateway.engine.policies.config.IgnoredResourcesConfig;
import io.apiman.gateway.engine.policies.i18n.Messages;
import io.apiman.gateway.engine.policy.IPolicyChain;
import io.apiman.gateway.engine.policy.IPolicyContext;

/**
* A simple policy that causes a failure if the paths of the inbound
* request matching the configured set of regular expressions.
*
* @author rubenrm1@gmail.com
*/
public class IgnoredResourcesPolicy extends AbstractMappedPolicy<IgnoredResourcesConfig> {

/**
* Constructor.
*/
public IgnoredResourcesPolicy() {
}

/**
* @see io.apiman.gateway.engine.policy.AbstractPolicy#getConfigurationClass()
*/
@Override
protected Class<IgnoredResourcesConfig> getConfigurationClass() {
return IgnoredResourcesConfig.class;
}

/**
* @see io.apiman.gateway.engine.policies.AbstractMappedPolicy#doApply(io.apiman.gateway.engine.beans.ServiceRequest, io.apiman.gateway.engine.policy.IPolicyContext, java.lang.Object, io.apiman.gateway.engine.policy.IPolicyChain)
*/
@Override
protected void doApply(ServiceRequest request, IPolicyContext context, IgnoredResourcesConfig config,
IPolicyChain<ServiceRequest> chain) {
if (!satisfiesAnyPath(config, request.getDestination())) {
super.doApply(request, context, config, chain);
} else {
IPolicyFailureFactoryComponent ffactory = context.getComponent(IPolicyFailureFactoryComponent.class);
String msg = Messages.i18n.format("IgnoredResourcesPolicy.PathsToIgnore", request.getDestination()); //$NON-NLS-1$
PolicyFailure failure = ffactory.createFailure(PolicyFailureType.NotFound, PolicyFailureCodes.PATHS_TO_IGNORE, msg);
chain.doFailure(failure);
}
}

/**
* Evaluates whether the destination provided matches any of the configured pathsToIgnore
*
* @param config The {@link IgnoredResourcesConfig} containing the pathsToIgnore
* @param destination The destination to evaluate
* @return true if any path matches the destination. false otherwise
*/
private boolean satisfiesAnyPath(IgnoredResourcesConfig config, String destination) {
for(String pathToIgnore : config.getPathsToIgnore()) {
if(destination.matches(pathToIgnore)) {
return true;
}
}
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ public final class PolicyFailureCodes {
public static final int BASIC_AUTH_REQUIRED = 10004;
public static final int RATE_LIMIT_EXCEEDED = 10005;
public static final int NO_USER_FOR_RATE_LIMITING = 10006;
public static final int PATHS_TO_IGNORE = 10007;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2014 JBoss Inc
*
* 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 io.apiman.gateway.engine.policies.config;


import java.util.ArrayList;
import java.util.List;

import org.jboss.errai.common.client.api.annotations.Portable;

/**
* Configuration object for the Ignored Resources policy.
*
* @author rubenrm1@gmail.com
*/
@Portable
public class IgnoredResourcesConfig {

private List<String> pathsToIgnore = new ArrayList<String>();

/**
* Constructor.
*/
public IgnoredResourcesConfig() {
}

/**
* @return the pathsToIgnore
*/
public List<String> getPathsToIgnore() {
return pathsToIgnore;
}

/**
* @param pathsToIgnore the pathsToIgnore to set
*/
public void setPathsToIgnore(List<String> pathsToIgnore) {
this.pathsToIgnore = pathsToIgnore;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
<bean id="ipWhiteList" class="io.apiman.gateway.engine.policies.IPWhitelistPolicy" />
<bean id="ipBlackList" class="io.apiman.gateway.engine.policies.IPBlacklistPolicy" />
<bean id="basicAuth" class="io.apiman.gateway.engine.policies.BasicAuthenticationPolicy" />
<bean id="ignoredRes" class="io.apiman.gateway.engine.policies.IgnoredResourcesPolicy" />

<service ref="ipWhiteList" interface="io.apiman.gateway.engine.policy.IPolicy" />
<service ref="ipBlackList" interface="io.apiman.gateway.engine.policy.IPolicy" />
<service ref="basicAuth" interface="io.apiman.gateway.engine.policy.IPolicy" />
<service ref="ignoredRes" interface="io.apiman.gateway.engine.policy.IPolicy" />

</blueprint>
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ IPWhitelistPolicy.NotWhitelisted=Inbound IP address "{0}" is not included in the
IPBlacklistPolicy.Blacklisted=Inbound IP address "{0}" has been black-listed.
BasicAuthenticationPolicy.AuthenticationFailed=BASIC authentication failed.
RateLimitingPolicy.NoUser=No authenticated user available for rate limiting.
RateLimitingPolicy.RateExceeded=Rate limit exceeded.
RateLimitingPolicy.RateExceeded=Rate limit exceeded.
IgnoredResourcesPolicy.PathsToIgnore=Requested path "{0}" has been ignored.
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright 2014 JBoss Inc
*
* 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 io.apiman.gateway.engine.policies;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import io.apiman.gateway.engine.beans.PolicyFailure;
import io.apiman.gateway.engine.beans.PolicyFailureType;
import io.apiman.gateway.engine.beans.ServiceRequest;
import io.apiman.gateway.engine.components.IPolicyFailureFactoryComponent;
import io.apiman.gateway.engine.policies.config.IgnoredResourcesConfig;
import io.apiman.gateway.engine.policy.IPolicyChain;
import io.apiman.gateway.engine.policy.IPolicyContext;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;
import org.mockito.Mockito;

/**
* Unit test
*
* @author rubenrm1@gmail.com
*
*/
@SuppressWarnings({ "unchecked" })
public class IgnoredResourcesPolicyTest {

@Test
public void testParseConfiguration() {
IgnoredResourcesPolicy policy = new IgnoredResourcesPolicy();

String config = "{}";
Object parsed = policy.parseConfiguration(config);
assertNotNull(parsed);
assertEquals(IgnoredResourcesConfig.class, parsed.getClass());

IgnoredResourcesConfig parsedConfig = (IgnoredResourcesConfig) parsed;
assertNotNull(parsedConfig.getPathsToIgnore());
assertTrue(parsedConfig.getPathsToIgnore().isEmpty());

// Single Path
config = "{" +
" \"pathsToIgnore\" : [" +
" \"/invoices/.+/items/.+\"" +
" ]" +
" }";
parsed = policy.parseConfiguration(config);
parsedConfig = (IgnoredResourcesConfig) parsed;
assertNotNull(parsedConfig.getPathsToIgnore());
List<String> expectedConfiguration = Arrays.asList("/invoices/.+/items/.+");
assertEquals(expectedConfiguration, parsedConfig.getPathsToIgnore());

// Multiple Paths
config = "{" +
" \"pathsToIgnore\" : [" +
" \"/invoices/.+/items/.+\"," +
" \"/items/.+\"" +
" ]" +
" }";
parsed = policy.parseConfiguration(config);
parsedConfig = (IgnoredResourcesConfig) parsed;
assertNotNull(parsedConfig.getPathsToIgnore());
expectedConfiguration = new ArrayList<>();
expectedConfiguration.add("/invoices/.+/items/.+");
expectedConfiguration.add("/items/.+");
assertEquals(expectedConfiguration, parsedConfig.getPathsToIgnore());
}

@Test
public void testApply() {
IgnoredResourcesPolicy policy = new IgnoredResourcesPolicy();

String json = "{" +
" \"pathsToIgnore\" : [" +
" \"/invoices/.+/items/.+\"," +
" \"/items/.+\"" +
" ]" +
" }";
Object config = policy.parseConfiguration(json);

ServiceRequest request = new ServiceRequest();
request.setType("GET");
request.setApiKey("12345");
request.setRemoteAddr("1.2.3.4");
request.setDestination("/invoices/1");
IPolicyContext context = Mockito.mock(IPolicyContext.class);
IPolicyChain<ServiceRequest> chain = Mockito.mock(IPolicyChain.class);

// Success
policy.apply(request, context, config, chain);

// Success
request.setDestination("/invoices");
policy.apply(request, context, config, chain);

// Success
request.setDestination("/invoices/items");
policy.apply(request, context, config, chain);

// Success
request.setDestination("/invoices/items/13");
policy.apply(request, context, config, chain);
Mockito.verify(chain, Mockito.times(4)).doApply(request);

// Failure
final PolicyFailure failure = new PolicyFailure();
Mockito.when(context.getComponent(IPolicyFailureFactoryComponent.class)).thenReturn(
new IPolicyFailureFactoryComponent() {
@Override
public PolicyFailure createFailure(PolicyFailureType type, int failureCode, String message) {
return failure;
}
});
chain = Mockito.mock(IPolicyChain.class);
request.setDestination("/invoices/23/items/43");
policy.apply(request, context, config, chain);

// Failure
request.setDestination("/items/43");
policy.apply(request, context, config, chain);
Mockito.verify(chain, Mockito.times(2)).doFailure(failure);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ private void writeFailure(HttpServletResponse resp, PolicyFailure policyFailure)
errorCode = 401;
} else if (policyFailure.getType() == PolicyFailureType.Authorization) {
errorCode = 403;
} else if (policyFailure.getType() == PolicyFailureType.NotFound) {
errorCode = 404;
}
resp.setStatus(errorCode);
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2014 JBoss Inc
*
* 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 io.apiman.gateway.test;

import org.junit.Test;

/**
* Make sure the Ignored Resources policy works.
*
* @author rubenrm1@gmail.com
*/
public class Policy_IgnoredResourcesTest extends AbstractGatewayTest {

@Test
public void test() throws Exception {
runTestPlan("test-plans/policies/ignored-resources-testPlan.xml"); //$NON-NLS-1$
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
PUT /api/services admin/admin
Content-Type: application/json

{
"organizationId" : "Policy_IgnoredResourcesTest",
"serviceId" : "echo",
"version" : "1.0.0",
"endpointType" : "REST",
"endpoint" : "${apiman-gateway-test.endpoints.echo}/"
}
----
204