Pengfei Lu
Committed by Gerrit Code Review

Add an ACL application

- change both of the constructors in AclRule.class to be private
- change AclRule.class to be final
- remove useless reference

|URL|Notes|
|-|-|
|GET onos/v1/acl | Lists all existing ACL rules.|
|GET onos/v1/acl/remove/{id} | Removes an existing ACL rule by id|
|GET onos/v1/acl/clear | Clears ACL and reset all|
|POST onos/v1/acl/add | Adds a new ACL rule|

|Key|Value|Notes|
|-|-|-|
|ipProto | string | "TCP" or "UDP" or "ICMP" (ignoring case)|
|srcIp | IPv4 address[/mask] | Either src-ip or dst-ip must be specified.|
|dstIp | IPv4 address[/mask] | Either src-ip or dst-ip must be specified.|
|dstTpPort | number | Valid when nw-proto == "TCP" or "UDP".|
|action | string | "DENY" or "ALLOW" (ignoring case), set to "DENY" if not specified.|

Change-Id: I55170d5f50814eabef43b1bf2ee33af41b5987e4
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~ Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
5 + ~ Advisers: Keqiu Li and Heng Qi
6 + ~ This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
7 + ~ and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
8 + ~
9 + ~ Licensed under the Apache License, Version 2.0 (the "License");
10 + ~ you may not use this file except in compliance with the License.
11 + ~ You may obtain a copy of the License at
12 + ~
13 + ~ http://www.apache.org/licenses/LICENSE-2.0
14 + ~
15 + ~ Unless required by applicable law or agreed to in writing, software
16 + ~ distributed under the License is distributed on an "AS IS" BASIS,
17 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 + ~ See the License for the specific language governing permissions and
19 + ~ limitations under the License.
20 + -->
21 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
22 + <modelVersion>4.0.0</modelVersion>
23 +
24 + <parent>
25 + <groupId>org.onosproject</groupId>
26 + <artifactId>onos-apps</artifactId>
27 + <version>1.3.0-SNAPSHOT</version>
28 + <relativePath>../pom.xml</relativePath>
29 + </parent>
30 +
31 + <artifactId>onos-app-acl</artifactId>
32 + <version>1.3.0-SNAPSHOT</version>
33 + <packaging>bundle</packaging>
34 +
35 + <description>ONOS ACL application</description>
36 + <url>http://onosproject.org</url>
37 +
38 + <properties>
39 + <onos.version>1.3.0-SNAPSHOT</onos.version>
40 + <onos.app.name>org.onosproject.acl</onos.app.name>
41 + <onos.app.origin>Pengfei Lu</onos.app.origin>
42 + <web.context>/onos/v1/acl</web.context>
43 + </properties>
44 +
45 + <dependencies>
46 + <dependency>
47 + <groupId>com.google.guava</groupId>
48 + <artifactId>guava</artifactId>
49 + <version>18.0</version>
50 + </dependency>
51 +
52 + <dependency>
53 + <groupId>javax.ws.rs</groupId>
54 + <artifactId>jsr311-api</artifactId>
55 + <version>1.1.1</version>
56 + </dependency>
57 +
58 + <dependency>
59 + <groupId>org.onosproject</groupId>
60 + <artifactId>onlab-junit</artifactId>
61 + <version>${onos.version}</version>
62 + </dependency>
63 +
64 + <dependency>
65 + <groupId>org.onosproject</groupId>
66 + <artifactId>onos-rest</artifactId>
67 + <version>${onos.version}</version>
68 + </dependency>
69 +
70 + <dependency>
71 + <groupId>org.onosproject</groupId>
72 + <artifactId>onos-core-serializers</artifactId>
73 + <version>${onos.version}</version>
74 + </dependency>
75 +
76 + <dependency>
77 + <groupId>com.sun.jersey.jersey-test-framework</groupId>
78 + <artifactId>jersey-test-framework-core</artifactId>
79 + <version>1.19</version>
80 + </dependency>
81 +
82 + <dependency>
83 + <groupId>org.easymock</groupId>
84 + <artifactId>easymock</artifactId>
85 + <version>3.2</version>
86 + </dependency>
87 +
88 + <dependency>
89 + <groupId>com.sun.jersey.jersey-test-framework</groupId>
90 + <artifactId>jersey-test-framework-grizzly2</artifactId>
91 + <version>1.19</version>
92 + </dependency>
93 +
94 + <dependency>
95 + <groupId>org.onosproject</groupId>
96 + <artifactId>onlab-misc</artifactId>
97 + <version>${onos.version}</version>
98 + </dependency>
99 +
100 + </dependencies>
101 +
102 + <build>
103 + <plugins>
104 + <plugin>
105 + <groupId>org.apache.felix</groupId>
106 + <artifactId>maven-bundle-plugin</artifactId>
107 + <version>2.5.3</version>
108 + <extensions>true</extensions>
109 + <configuration>
110 + <instructions>
111 + <_wab>src/main/webapp/</_wab>
112 + <Bundle-SymbolicName>
113 + ${project.groupId}.${project.artifactId}
114 + </Bundle-SymbolicName>
115 + <Import-Package>
116 + org.slf4j,
117 + org.osgi.framework,
118 + javax.ws.rs,javax.ws.rs.core,
119 + com.fasterxml.jackson*,
120 + com.sun.jersey.api.core,
121 + com.sun.jersey.spi.container.servlet,
122 + com.sun.jersey.server.impl.container.servlet,
123 + org.onlab.packet.*,
124 + org.onlab.rest.*,
125 + org.onosproject.*,
126 + org.onlab.util.*,
127 + com.google.common.*;
128 + </Import-Package>
129 + <Web-ContextPath>${web.context}</Web-ContextPath>
130 + </instructions>
131 + </configuration>
132 + </plugin>
133 + <plugin>
134 + <groupId>org.apache.maven.plugins</groupId>
135 + <artifactId>maven-compiler-plugin</artifactId>
136 + <version>2.5.1</version>
137 + <configuration>
138 + <source>1.8</source>
139 + <target>1.8</target>
140 + </configuration>
141 + </plugin>
142 + <plugin>
143 + <groupId>org.apache.felix</groupId>
144 + <artifactId>maven-scr-plugin</artifactId>
145 + <version>1.20.0</version>
146 + <executions>
147 + <execution>
148 + <id>generate-scr-srcdescriptor</id>
149 + <goals>
150 + <goal>scr</goal>
151 + </goals>
152 + </execution>
153 + </executions>
154 + <configuration>
155 + <supportedProjectTypes>
156 + <supportedProjectType>bundle</supportedProjectType>
157 + <supportedProjectType>war</supportedProjectType>
158 + </supportedProjectTypes>
159 + </configuration>
160 + </plugin>
161 + <plugin>
162 + <groupId>org.onosproject</groupId>
163 + <artifactId>onos-maven-plugin</artifactId>
164 + <version>1.4-SNAPSHOT</version>
165 + <executions>
166 + <execution>
167 + <id>cfg</id>
168 + <phase>generate-resources</phase>
169 + <goals>
170 + <goal>cfg</goal>
171 + </goals>
172 + </execution>
173 + <execution>
174 + <id>app</id>
175 + <phase>package</phase>
176 + <goals>
177 + <goal>app</goal>
178 + </goals>
179 + </execution>
180 + </executions>
181 + </plugin>
182 + </plugins>
183 + </build>
184 +
185 +</project>
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl;
21 +
22 +import com.google.common.base.MoreObjects;
23 +import org.onlab.packet.IPv4;
24 +import org.onlab.packet.Ip4Prefix;
25 +import org.onosproject.core.IdGenerator;
26 +
27 +import java.util.Objects;
28 +
29 +import static com.google.common.base.Preconditions.checkNotNull;
30 +import static com.google.common.base.Preconditions.checkState;
31 +
32 +/**
33 + * ACL rule class.
34 + */
35 +public final class AclRule {
36 +
37 + private final RuleId id;
38 +
39 + private final Ip4Prefix srcIp;
40 + private final Ip4Prefix dstIp;
41 + private final byte ipProto;
42 + private final short dstTpPort;
43 + private final Action action;
44 +
45 + private static IdGenerator idGenerator;
46 +
47 + /**
48 + * Enum type for ACL rule's action.
49 + */
50 + public enum Action {
51 + DENY, ALLOW
52 + }
53 +
54 + /**
55 + * Constructor for serializer.
56 + */
57 + private AclRule() {
58 + this.id = null;
59 + this.srcIp = null;
60 + this.dstIp = null;
61 + this.ipProto = 0;
62 + this.dstTpPort = 0;
63 + this.action = null;
64 + }
65 +
66 + /**
67 + * Create a new ACL rule.
68 + *
69 + * @param srcIp source IP address
70 + * @param dstIp destination IP address
71 + * @param ipProto IP protocol
72 + * @param dstTpPort destination transport layer port
73 + * @param action ACL rule's action
74 + */
75 + private AclRule(Ip4Prefix srcIp,
76 + Ip4Prefix dstIp,
77 + byte ipProto,
78 + short dstTpPort,
79 + Action action) {
80 + checkState(idGenerator != null, "Id generator is not bound.");
81 + this.id = RuleId.valueOf(idGenerator.getNewId());
82 + this.srcIp = srcIp;
83 + this.dstIp = dstIp;
84 + this.ipProto = ipProto;
85 + this.dstTpPort = dstTpPort;
86 + this.action = action;
87 + }
88 +
89 + /**
90 + * Check if the first CIDR address is in (or the same as) the second CIDR address.
91 + */
92 + private boolean checkCIDRinCIDR(Ip4Prefix cidrAddr1, Ip4Prefix cidrAddr2) {
93 + if (cidrAddr2 == null) {
94 + return true;
95 + } else if (cidrAddr1 == null) {
96 + return false;
97 + }
98 + if (cidrAddr1.prefixLength() < cidrAddr2.prefixLength()) {
99 + return false;
100 + }
101 + int offset = 32 - cidrAddr2.prefixLength();
102 +
103 + int cidr1Prefix = cidrAddr1.address().toInt();
104 + int cidr2Prefix = cidrAddr2.address().toInt();
105 + cidr1Prefix = cidr1Prefix >> offset;
106 + cidr2Prefix = cidr2Prefix >> offset;
107 + cidr1Prefix = cidr1Prefix << offset;
108 + cidr2Prefix = cidr2Prefix << offset;
109 +
110 + return (cidr1Prefix == cidr2Prefix);
111 + }
112 +
113 + /**
114 + * Check if this ACL rule match the given ACL rule.
115 + * @param r ACL rule to check against
116 + * @return true if this ACL rule matches the given ACL ruleule.
117 + */
118 + public boolean checkMatch(AclRule r) {
119 + return (this.dstTpPort == r.dstTpPort || r.dstTpPort == 0)
120 + && (this.ipProto == r.ipProto || r.ipProto == 0)
121 + && (checkCIDRinCIDR(this.srcIp(), r.srcIp()))
122 + && (checkCIDRinCIDR(this.dstIp(), r.dstIp()));
123 + }
124 +
125 + /**
126 + * Returns a new ACL rule builder.
127 + *
128 + * @return ACL rule builder
129 + */
130 + public static Builder builder() {
131 + return new Builder();
132 + }
133 +
134 + /**
135 + * Builder of an ACL rule.
136 + */
137 + public static final class Builder {
138 +
139 + private Ip4Prefix srcIp = null;
140 + private Ip4Prefix dstIp = null;
141 + private byte ipProto = 0;
142 + private short dstTpPort = 0;
143 + private Action action = Action.DENY;
144 +
145 + private Builder() {
146 + // Hide constructor
147 + }
148 +
149 + /**
150 + * Sets the source IP address for the ACL rule that will be built.
151 + *
152 + * @param srcIp source IP address to use for built ACL rule
153 + * @return this builder
154 + */
155 + public Builder srcIp(String srcIp) {
156 + this.srcIp = Ip4Prefix.valueOf(srcIp);
157 + return this;
158 + }
159 +
160 + /**
161 + * Sets the destination IP address for the ACL rule that will be built.
162 + *
163 + * @param dstIp destination IP address to use for built ACL rule
164 + * @return this builder
165 + */
166 + public Builder dstIp(String dstIp) {
167 + this.dstIp = Ip4Prefix.valueOf(dstIp);
168 + return this;
169 + }
170 +
171 + /**
172 + * Sets the IP protocol for the ACL rule that will be built.
173 + *
174 + * @param ipProto IP protocol to use for built ACL rule
175 + * @return this builder
176 + */
177 + public Builder ipProto(byte ipProto) {
178 + this.ipProto = ipProto;
179 + return this;
180 + }
181 +
182 + /**
183 + * Sets the destination transport layer port for the ACL rule that will be built.
184 + *
185 + * @param dstTpPort destination transport layer port to use for built ACL rule
186 + * @return this builder
187 + */
188 + public Builder dstTpPort(short dstTpPort) {
189 + if ((ipProto == IPv4.PROTOCOL_TCP || ipProto == IPv4.PROTOCOL_UDP)) {
190 + this.dstTpPort = dstTpPort;
191 + }
192 + return this;
193 + }
194 +
195 + /**
196 + * Sets the action for the ACL rule that will be built.
197 + *
198 + * @param action action to use for built ACL rule
199 + * @return this builder
200 + */
201 + public Builder action(Action action) {
202 + this.action = action;
203 + return this;
204 + }
205 +
206 + /**
207 + * Builds an ACL rule from the accumulated parameters.
208 + * @return ACL rule instance
209 + */
210 + public AclRule build() {
211 + checkState(srcIp != null && dstIp != null, "Either srcIp or dstIp must be assigned.");
212 + checkState(ipProto == 0 || ipProto == IPv4.PROTOCOL_ICMP
213 + || ipProto == IPv4.PROTOCOL_TCP || ipProto == IPv4.PROTOCOL_UDP,
214 + "ipProto must be assigned to TCP, UDP, or ICMP.");
215 + return new AclRule(
216 + srcIp,
217 + dstIp,
218 + ipProto,
219 + dstTpPort,
220 + action
221 + );
222 + }
223 +
224 + }
225 +
226 + /**
227 + * Binds an id generator for unique ACL rule id generation.
228 + *
229 + * Note: A generator cannot be bound if there is already a generator bound.
230 + *
231 + * @param newIdGenerator id generator
232 + */
233 + public static void bindIdGenerator(IdGenerator newIdGenerator) {
234 + checkState(idGenerator == null, "Id generator is already bound.");
235 + idGenerator = checkNotNull(newIdGenerator);
236 + }
237 +
238 + public RuleId id() {
239 + return id;
240 + }
241 +
242 + public Ip4Prefix srcIp() {
243 + return srcIp;
244 + }
245 +
246 + public Ip4Prefix dstIp() {
247 + return this.dstIp;
248 + }
249 +
250 + public byte ipProto() {
251 + return ipProto;
252 + }
253 +
254 + public short dstTpPort() {
255 + return dstTpPort;
256 + }
257 +
258 + public Action action() {
259 + return action;
260 + }
261 +
262 + @Override
263 + public int hashCode() {
264 + return Objects.hash(action,
265 + id.fingerprint(),
266 + ipProto,
267 + srcIp,
268 + dstIp,
269 + dstTpPort);
270 + }
271 +
272 + @Override
273 + public boolean equals(Object obj) {
274 + if (this == obj) {
275 + return true;
276 + }
277 + if (obj instanceof AclRule) {
278 + AclRule that = (AclRule) obj;
279 + return Objects.equals(id, that.id) &&
280 + Objects.equals(srcIp, that.srcIp) &&
281 + Objects.equals(dstIp, that.dstIp) &&
282 + Objects.equals(ipProto, that.ipProto) &&
283 + Objects.equals(dstTpPort, that.dstTpPort) &&
284 + Objects.equals(action, that.action);
285 + }
286 + return false;
287 + }
288 +
289 + @Override
290 + public String toString() {
291 + return MoreObjects.toStringHelper(this)
292 + .omitNullValues()
293 + .add("id", id)
294 + .add("srcIp", srcIp)
295 + .add("dstIp", dstIp)
296 + .add("ipProto", ipProto)
297 + .add("dstTpPort", dstTpPort)
298 + .add("action", action)
299 + .toString();
300 + }
301 +
302 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl;
21 +
22 +import java.util.List;
23 +
24 +/**
25 + * Service interface exported by ACL application.
26 + */
27 +public interface AclService {
28 +
29 + /**
30 + * Gets a list containing all ACL rules.
31 + * @return a list containing all ACL rules
32 + */
33 + List<AclRule> getAclRules();
34 +
35 + /**
36 + * Adds a new ACL rule.
37 + * @param rule ACL rule
38 + * @return true if successfully added, otherwise false
39 + */
40 + boolean addAclRule(AclRule rule);
41 +
42 + /**
43 + * Removes an exsiting ACL rule by rule id.
44 + * @param ruleId ACL rule identifier
45 + */
46 + void removeAclRule(RuleId ruleId);
47 +
48 + /**
49 + * Clears ACL and resets all.
50 + */
51 + void clearAcl();
52 +
53 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl;
21 +
22 +import org.onosproject.net.DeviceId;
23 +import org.onosproject.net.flow.FlowRule;
24 +import org.onosproject.store.Store;
25 +
26 +import java.util.List;
27 +import java.util.Set;
28 +
29 +/**
30 + * Service interface exported by ACL distributed store.
31 + */
32 +public interface AclStore extends Store {
33 +
34 + /**
35 + * Gets a list containing all ACL rules.
36 + * @return a list containing all ACL rules
37 + */
38 + List<AclRule> getAclRules();
39 +
40 + /**
41 + * Adds a new ACL rule.
42 + * @param rule new ACL rule
43 + */
44 + void addAclRule(AclRule rule);
45 +
46 + /**
47 + * Gets an existing ACL rule.
48 + * @param ruleId ACL rule id
49 + * @return ACL rule with the given id
50 + */
51 + AclRule getAclRule(RuleId ruleId);
52 +
53 + /**
54 + * Removes an existing ACL rule by rule id.
55 + * @param ruleId ACL rule id
56 + */
57 + void removeAclRule(RuleId ruleId);
58 +
59 + /**
60 + * Clears ACL and reset all.
61 + */
62 + void clearAcl();
63 +
64 + /**
65 + * Gets the current priority for new ACL flow rule by device id.
66 + * @param deviceId device id
67 + * @return new ACL flow rule's priority in the given device
68 + */
69 + int getPriorityByDevice(DeviceId deviceId);
70 +
71 + /**
72 + * Gets a set containing all ACL flow rules belonging to a given ACL rule.
73 + * @param ruleId ACL rule id
74 + * @return a set containing all ACL flow rules belonging to the given ACL rule
75 + */
76 + Set<FlowRule> getFlowByRule(RuleId ruleId);
77 +
78 + /**
79 + * Adds a new mapping from ACL rule to ACL flow rule.
80 + * @param ruleId ACL rule id
81 + * @param flowRule ACL flow rule
82 + */
83 + void addRuleToFlowMapping(RuleId ruleId, FlowRule flowRule);
84 +
85 + /**
86 + * Removes an existing mapping from ACL rule to ACL flow rule.
87 + * @param ruleId ACL rule id
88 + */
89 + void removeRuleToFlowMapping(RuleId ruleId);
90 +
91 + /**
92 + * Gets a list containing all allowing ACL rules matching a given denying ACL rule.
93 + * @param denyingRuleId denying ACL rule id
94 + * @return a list containing all allowing ACL rules matching the given denying ACL rule
95 + */
96 + List<RuleId> getAllowingRuleByDenyingRule(RuleId denyingRuleId);
97 +
98 + /**
99 + * Adds a new mapping from denying ACL rule to allowing ACL rule.
100 + * @param denyingRuleId denying ACL rule id
101 + * @param allowingRuleId allowing ACL rule id
102 + */
103 + void addDenyToAllowMapping(RuleId denyingRuleId, RuleId allowingRuleId);
104 +
105 + /**
106 + * Removes an exsiting mapping from denying ACL rule to allowing ACL rule.
107 + * @param denyingRuleId denying ACL rule id
108 + */
109 + void removeDenyToAllowMapping(RuleId denyingRuleId);
110 +
111 + /**
112 + * Checks if an existing ACL rule already works in a given device.
113 + * @param ruleId ACL rule id
114 + * @param deviceId devide id
115 + * @return true if the given ACL rule works in the given device
116 + */
117 + boolean checkIfRuleWorksInDevice(RuleId ruleId, DeviceId deviceId);
118 +
119 + /**
120 + * Adds a new mapping from ACL rule to device.
121 + * @param ruleId ACL rule id
122 + * @param deviceId device id
123 + */
124 + void addRuleToDeviceMapping(RuleId ruleId, DeviceId deviceId);
125 +
126 + /**
127 + * Removes an existing mapping from ACL rule to device.
128 + * @param ruleId ACL rule id
129 + */
130 + void removeRuleToDeviceMapping(RuleId ruleId);
131 +
132 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl;
21 +
22 +import com.fasterxml.jackson.core.JsonParser;
23 +import com.fasterxml.jackson.core.JsonToken;
24 +import com.fasterxml.jackson.databind.JsonNode;
25 +import com.fasterxml.jackson.databind.ObjectMapper;
26 +import com.fasterxml.jackson.databind.node.ArrayNode;
27 +import com.fasterxml.jackson.databind.node.ObjectNode;
28 +import org.onlab.packet.IPv4;
29 +import org.onosproject.rest.AbstractWebResource;
30 +import org.slf4j.Logger;
31 +import org.slf4j.LoggerFactory;
32 +
33 +import javax.ws.rs.GET;
34 +import javax.ws.rs.POST;
35 +import javax.ws.rs.Path;
36 +import javax.ws.rs.PathParam;
37 +import javax.ws.rs.core.MediaType;
38 +import javax.ws.rs.core.Response;
39 +import java.io.IOException;
40 +import java.io.InputStream;
41 +import java.util.List;
42 +
43 +/**
44 + * REST resource for interacting with ACL application.
45 + */
46 +@Path("")
47 +public class AclWebResource extends AbstractWebResource {
48 +
49 + private final Logger log = LoggerFactory.getLogger(getClass());
50 +
51 + /**
52 + * Processes user's GET HTTP request for querying ACL rules.
53 + * @return response to the request
54 + */
55 + @GET
56 + public Response queryAclRule() {
57 + List<AclRule> rules = get(AclService.class).getAclRules();
58 + ObjectMapper mapper = new ObjectMapper();
59 + ObjectNode root = mapper.createObjectNode();
60 + ArrayNode arrayNode = mapper.createArrayNode();
61 + for (AclRule rule : rules) {
62 + ObjectNode node = mapper.createObjectNode();
63 + node.put("id", rule.id().toString());
64 + if (rule.srcIp() != null) {
65 + node.put("srcIp", rule.srcIp().toString());
66 + }
67 + if (rule.dstIp() != null) {
68 + node.put("dstIp", rule.dstIp().toString());
69 + }
70 + if (rule.ipProto() != 0) {
71 + switch (rule.ipProto()) {
72 + case IPv4.PROTOCOL_ICMP:
73 + node.put("ipProto", "ICMP");
74 + break;
75 + case IPv4.PROTOCOL_TCP:
76 + node.put("ipProto", "TCP");
77 + break;
78 + case IPv4.PROTOCOL_UDP:
79 + node.put("ipProto", "UDP");
80 + break;
81 + default:
82 + break;
83 + }
84 + }
85 + if (rule.dstTpPort() != 0) {
86 + node.put("dstTpPort", rule.dstTpPort());
87 + }
88 + node.put("action", rule.action().toString());
89 + arrayNode.add(node);
90 + }
91 + root.set("ACL rules", arrayNode);
92 + return Response.ok(root.toString(), MediaType.APPLICATION_JSON_TYPE).build();
93 + }
94 +
95 + /**
96 + * Processes user's POST HTTP request for add ACL rules.
97 + * @param stream input stream
98 + * @return response to the request
99 + */
100 + @POST
101 + @Path("add")
102 + public Response addAclRule(InputStream stream) {
103 + AclRule newRule;
104 + try {
105 + newRule = jsonToRule(stream);
106 + } catch (Exception e) {
107 + return Response.ok("{\"status\" : \"Failed! " + e.getMessage() + "\"}").build();
108 + }
109 +
110 + String status;
111 + if (get(AclService.class).addAclRule(newRule)) {
112 + status = "Success! New ACL rule is added.";
113 + } else {
114 + status = "Failed! New ACL rule matches an existing rule.";
115 + }
116 + return Response.ok("{\"status\" : \"" + status + "\"}").build();
117 + }
118 +
119 + /**
120 + * Processes user's GET HTTP request for removing ACL rule.
121 + * @param id ACL rule id (in hex string format)
122 + * @return response to the request
123 + */
124 + @GET
125 + @Path("remove/{id}")
126 + public Response removeAclRule(@PathParam("id") String id) {
127 + String status;
128 + RuleId ruleId = new RuleId(Long.parseLong(id.substring(2), 16));
129 + if (get(AclStore.class).getAclRule(ruleId) == null) {
130 + status = "Failed! There is no ACL rule with this id.";
131 + } else {
132 + get(AclService.class).removeAclRule(ruleId);
133 + status = "Success! ACL rule(id:" + id + ") is removed.";
134 + }
135 + return Response.ok("{\"status\" : \"" + status + "\"}").build();
136 + }
137 +
138 + /**
139 + * Processes user's GET HTTP request for clearing ACL.
140 + * @return response to the request
141 + */
142 + @GET
143 + @Path("clear")
144 + public Response clearACL() {
145 + get(AclService.class).clearAcl();
146 + return Response.ok("{\"status\" : \"ACL is cleared.\"}").build();
147 + }
148 +
149 + /**
150 + * Exception class for parsing a invalid ACL rule.
151 + */
152 + private class AclRuleParseException extends Exception {
153 + public AclRuleParseException(String message) {
154 + super(message);
155 + }
156 + }
157 +
158 + /**
159 + * Turns a JSON string into an ACL rule instance.
160 + */
161 + private AclRule jsonToRule(InputStream stream) throws AclRuleParseException, IOException {
162 + ObjectMapper mapper = new ObjectMapper();
163 + JsonNode jsonNode = mapper.readTree(stream);
164 + JsonParser jp = jsonNode.traverse();
165 + AclRule.Builder rule = AclRule.builder();
166 + jp.nextToken();
167 + if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
168 + throw new AclRuleParseException("Expected START_OBJECT");
169 + }
170 +
171 + while (jp.nextToken() != JsonToken.END_OBJECT) {
172 + if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
173 + throw new AclRuleParseException("Expected FIELD_NAME");
174 + }
175 +
176 + String key = jp.getCurrentName();
177 + jp.nextToken();
178 + String value = jp.getText();
179 + if ("".equals(value)) {
180 + continue;
181 + }
182 +
183 + if ("srcIp".equals(key)) {
184 + rule.srcIp(value);
185 + } else if ("dstIp".equals(key)) {
186 + rule.dstIp(value);
187 + } else if ("ipProto".equals(key)) {
188 + if ("TCP".equalsIgnoreCase(value)) {
189 + rule.ipProto(IPv4.PROTOCOL_TCP);
190 + } else if ("UDP".equalsIgnoreCase(value)) {
191 + rule.ipProto(IPv4.PROTOCOL_UDP);
192 + } else if ("ICMP".equalsIgnoreCase(value)) {
193 + rule.ipProto(IPv4.PROTOCOL_ICMP);
194 + } else {
195 + throw new AclRuleParseException("ipProto must be assigned to TCP, UDP, or ICMP.");
196 + }
197 + } else if ("dstTpPort".equals(key)) {
198 + try {
199 + rule.dstTpPort(Short.parseShort(value));
200 + } catch (NumberFormatException e) {
201 + throw new AclRuleParseException("dstTpPort must be assigned to a numerical value.");
202 + }
203 + } else if ("action".equals(key)) {
204 + if (!"allow".equalsIgnoreCase(value) && !"deny".equalsIgnoreCase(value)) {
205 + throw new AclRuleParseException("action must be assigned to ALLOW or DENY.");
206 + }
207 + if ("allow".equalsIgnoreCase(value)) {
208 + rule.action(AclRule.Action.ALLOW);
209 + }
210 + }
211 + }
212 + return rule.build();
213 + }
214 +
215 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl;
21 +
22 +/**
23 + * ACL rule identifier suitable as an external key.
24 + * <p>This class is immutable.</p>
25 + */
26 +public final class RuleId {
27 + private final long value;
28 +
29 + /**
30 + * Creates an ACL rule identifier from the specified long value.
31 + *
32 + * @param value long value
33 + * @return ACL rule identifier
34 + */
35 + public static RuleId valueOf(long value) {
36 + return new RuleId(value);
37 + }
38 +
39 + /**
40 + * Constructor for serializer.
41 + */
42 + RuleId() {
43 + this.value = 0;
44 + }
45 +
46 + /**
47 + * Constructs the ID corresponding to a given long value.
48 + *
49 + * @param value the underlying value of this ID
50 + */
51 + RuleId(long value) {
52 + this.value = value;
53 + }
54 +
55 + /**
56 + * Returns the backing value.
57 + *
58 + * @return the value
59 + */
60 + public long fingerprint() {
61 + return value;
62 + }
63 +
64 + @Override
65 + public int hashCode() {
66 + return Long.hashCode(value);
67 + }
68 +
69 + @Override
70 + public boolean equals(Object obj) {
71 + if (obj == this) {
72 + return true;
73 + }
74 + if (!(obj instanceof RuleId)) {
75 + return false;
76 + }
77 + RuleId that = (RuleId) obj;
78 + return this.value == that.value;
79 + }
80 +
81 + @Override
82 + public String toString() {
83 + return "0x" + Long.toHexString(value);
84 + }
85 +}
This diff is collapsed. Click to expand it.
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl.impl;
21 +
22 +import com.google.common.collect.Collections2;
23 +import org.onos.acl.AclRule;
24 +import org.onos.acl.AclStore;
25 +import org.apache.felix.scr.annotations.Activate;
26 +import org.apache.felix.scr.annotations.Component;
27 +import org.apache.felix.scr.annotations.Deactivate;
28 +import org.apache.felix.scr.annotations.Reference;
29 +import org.apache.felix.scr.annotations.ReferenceCardinality;
30 +import org.apache.felix.scr.annotations.Service;
31 +import org.onlab.util.KryoNamespace;
32 +import org.onos.acl.RuleId;
33 +import org.onosproject.core.ApplicationId;
34 +import org.onosproject.core.CoreService;
35 +import org.onosproject.net.DeviceId;
36 +import org.onosproject.net.flow.FlowRule;
37 +import org.onosproject.store.AbstractStore;
38 +import org.onosproject.store.serializers.KryoNamespaces;
39 +import org.onosproject.store.service.ConsistentMap;
40 +import org.onosproject.store.service.Serializer;
41 +import org.onosproject.store.service.StorageService;
42 +import org.onosproject.store.service.Versioned;
43 +import org.slf4j.Logger;
44 +
45 +import java.util.ArrayList;
46 +import java.util.HashSet;
47 +import java.util.List;
48 +import java.util.Set;
49 +
50 +import static org.slf4j.LoggerFactory.getLogger;
51 +
52 +/**
53 + * Implementation of the ACL store service.
54 + */
55 +@Component(immediate = true)
56 +@Service
57 +public class DistributedAclStore extends AbstractStore implements AclStore {
58 +
59 + private final Logger log = getLogger(getClass());
60 + private final int defaultFlowMaxPriority = 30000;
61 +
62 + private ConsistentMap<RuleId, AclRule> ruleSet;
63 + private ConsistentMap<DeviceId, Integer> deviceToPriority;
64 + private ConsistentMap<RuleId, Set<DeviceId>> ruleToDevice;
65 + private ConsistentMap<RuleId, Set<FlowRule>> ruleToFlow;
66 + private ConsistentMap<RuleId, List<RuleId>> denyRuleToAllowRule;
67 +
68 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 + protected StorageService storageService;
70 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 + protected CoreService coreService;
72 +
73 + @Activate
74 + public void activate() {
75 + ApplicationId appId = coreService.getAppId("org.onosproject.acl");
76 +
77 + KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
78 + .register(KryoNamespaces.API)
79 + .register(AclRule.class)
80 + .register(AclRule.Action.class)
81 + .register(RuleId.class);
82 +
83 + ruleSet = storageService.<RuleId, AclRule>consistentMapBuilder()
84 + .withSerializer(Serializer.using(serializer.build()))
85 + .withName("acl-rule-set")
86 + .withApplicationId(appId)
87 + .withPurgeOnUninstall()
88 + .build();
89 +
90 + deviceToPriority = storageService.<DeviceId, Integer>consistentMapBuilder()
91 + .withSerializer(Serializer.using(serializer.build()))
92 + .withName("device-to-priority")
93 + .withApplicationId(appId)
94 + .withPurgeOnUninstall()
95 + .build();
96 +
97 + ruleToFlow = storageService.<RuleId, Set<FlowRule>>consistentMapBuilder()
98 + .withSerializer(Serializer.using(serializer.build()))
99 + .withName("rule-to-flow")
100 + .withApplicationId(appId)
101 + .withPurgeOnUninstall()
102 + .build();
103 +
104 + denyRuleToAllowRule = storageService.<RuleId, List<RuleId>>consistentMapBuilder()
105 + .withSerializer(Serializer.using(serializer.build()))
106 + .withName("deny-to-allow")
107 + .withApplicationId(appId)
108 + .withPurgeOnUninstall()
109 + .build();
110 +
111 + ruleToDevice = storageService.<RuleId, Set<DeviceId>>consistentMapBuilder()
112 + .withSerializer(Serializer.using(serializer.build()))
113 + .withName("rule-to-device")
114 + .withApplicationId(appId)
115 + .withPurgeOnUninstall()
116 + .build();
117 +
118 + log.info("Started");
119 + }
120 +
121 + @Deactivate
122 + public void deactive() {
123 + log.info("Stopped");
124 + }
125 +
126 + @Override
127 + public List<AclRule> getAclRules() {
128 + List<AclRule> aclRules = new ArrayList<>();
129 + aclRules.addAll(Collections2.transform(ruleSet.values(), Versioned::value));
130 + return aclRules;
131 + }
132 +
133 + @Override
134 + public void addAclRule(AclRule rule) {
135 + ruleSet.putIfAbsent(rule.id(), rule);
136 + }
137 +
138 + @Override
139 + public AclRule getAclRule(RuleId ruleId) {
140 + Versioned<AclRule> rule = ruleSet.get(ruleId);
141 + if (rule != null) {
142 + return rule.value();
143 + } else {
144 + return null;
145 + }
146 + }
147 +
148 + @Override
149 + public void removeAclRule(RuleId ruleId) {
150 + ruleSet.remove(ruleId);
151 + }
152 +
153 + @Override
154 + public void clearAcl() {
155 + ruleSet.clear();
156 + deviceToPriority.clear();
157 + ruleToFlow.clear();
158 + denyRuleToAllowRule.clear();
159 + ruleToDevice.clear();
160 + }
161 +
162 + @Override
163 + public int getPriorityByDevice(DeviceId deviceId) {
164 + return deviceToPriority.compute(deviceId,
165 + (id, priority) -> (priority == null) ? defaultFlowMaxPriority : (priority - 1))
166 + .value();
167 + }
168 +
169 + @Override
170 + public Set<FlowRule> getFlowByRule(RuleId ruleId) {
171 + Versioned<Set<FlowRule>> flowRuleSet = ruleToFlow.get(ruleId);
172 + if (flowRuleSet != null) {
173 + return flowRuleSet.value();
174 + } else {
175 + return null;
176 + }
177 + }
178 +
179 + @Override
180 + public void addRuleToFlowMapping(RuleId ruleId, FlowRule flowRule) {
181 + ruleToFlow.computeIf(ruleId,
182 + flowRuleSet -> (flowRuleSet == null || !flowRuleSet.contains(flowRule)),
183 + (id, flowRuleSet) -> {
184 + Set<FlowRule> newSet = new HashSet<>();
185 + if (flowRuleSet != null) {
186 + newSet.addAll(flowRuleSet);
187 + }
188 + newSet.add(flowRule);
189 + return newSet;
190 + });
191 + }
192 +
193 + @Override
194 + public void removeRuleToFlowMapping(RuleId ruleId) {
195 + ruleToFlow.remove(ruleId);
196 + }
197 +
198 + @Override
199 + public List<RuleId> getAllowingRuleByDenyingRule(RuleId denyingRuleId) {
200 + Versioned<List<RuleId>> allowRuleIdSet = denyRuleToAllowRule.get(denyingRuleId);
201 + if (allowRuleIdSet != null) {
202 + return allowRuleIdSet.value();
203 + } else {
204 + return null;
205 + }
206 + }
207 +
208 + @Override
209 + public void addDenyToAllowMapping(RuleId denyingRuleId, RuleId allowingRuleId) {
210 + denyRuleToAllowRule.computeIf(denyingRuleId,
211 + ruleIdList -> (ruleIdList == null || !ruleIdList.contains(allowingRuleId)),
212 + (id, ruleIdList) -> {
213 + ArrayList<RuleId> newList = new ArrayList<>();
214 + if (ruleIdList != null) {
215 + newList.addAll(ruleIdList);
216 + }
217 + newList.add(allowingRuleId);
218 + return newList;
219 + });
220 + }
221 +
222 + @Override
223 + public void removeDenyToAllowMapping(RuleId denyingRuleId) {
224 + denyRuleToAllowRule.remove(denyingRuleId);
225 + }
226 +
227 + @Override
228 + public boolean checkIfRuleWorksInDevice(RuleId ruleId, DeviceId deviceId) {
229 + return ruleToDevice.containsKey(ruleId) && ruleToDevice.get(ruleId).value().contains(deviceId);
230 + }
231 +
232 + @Override
233 + public void addRuleToDeviceMapping(RuleId ruleId, DeviceId deviceId) {
234 + ruleToDevice.computeIf(ruleId,
235 + deviceIdSet -> (deviceIdSet == null || !deviceIdSet.contains(deviceId)),
236 + (id, deviceIdSet) -> {
237 + Set<DeviceId> newSet = new HashSet<DeviceId>();
238 + if (deviceIdSet != null) {
239 + newSet.addAll(deviceIdSet);
240 + }
241 + newSet.add(deviceId);
242 + return newSet;
243 + });
244 + }
245 +
246 + @Override
247 + public void removeRuleToDeviceMapping(RuleId ruleId) {
248 + ruleToDevice.remove(ruleId);
249 + }
250 +
251 +}
...\ No newline at end of file ...\ No newline at end of file
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~ Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
5 + ~ Advisers: Keqiu Li and Heng Qi
6 + ~ This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
7 + ~ and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
8 + ~
9 + ~ Licensed under the Apache License, Version 2.0 (the "License");
10 + ~ you may not use this file except in compliance with the License.
11 + ~ You may obtain a copy of the License at
12 + ~
13 + ~ http://www.apache.org/licenses/LICENSE-2.0
14 + ~
15 + ~ Unless required by applicable law or agreed to in writing, software
16 + ~ distributed under the License is distributed on an "AS IS" BASIS,
17 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 + ~ See the License for the specific language governing permissions and
19 + ~ limitations under the License.
20 + -->
21 +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
22 + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
23 + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
24 + id="ONOS" version="2.5">
25 + <display-name>ACL application</display-name>
26 +
27 + <servlet>
28 + <servlet-name>JAX-RS Service</servlet-name>
29 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
30 + <init-param>
31 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
32 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
33 + </init-param>
34 + <init-param>
35 + <param-name>com.sun.jersey.config.property.classnames</param-name>
36 + <param-value>org.onos.acl.AclWebResource</param-value>
37 + </init-param>
38 + <load-on-startup>10</load-on-startup>
39 + </servlet>
40 +
41 + <servlet-mapping>
42 + <servlet-name>JAX-RS Service</servlet-name>
43 + <url-pattern>/*</url-pattern>
44 + </servlet-mapping>
45 +
46 +</web-app>
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +
21 +package org.onos.acl.web;
22 +
23 +import com.sun.jersey.api.client.WebResource;
24 +import org.onos.acl.AclService;
25 +import org.onos.acl.AclStore;
26 +import org.junit.After;
27 +import org.junit.Before;
28 +import org.junit.Test;
29 +import org.onlab.osgi.ServiceDirectory;
30 +import org.onlab.rest.BaseResource;
31 +import org.onos.acl.AclRule;
32 +import org.onosproject.core.IdGenerator;
33 +
34 +import java.io.IOException;
35 +import java.util.ArrayList;
36 +import java.util.List;
37 +import java.util.concurrent.atomic.AtomicLong;
38 +
39 +import static org.easymock.EasyMock.*;
40 +import static org.hamcrest.Matchers.containsString;
41 +import static org.junit.Assert.assertThat;
42 +
43 +/**
44 + * Test class for ACL application REST resource.
45 + */
46 +public class AclWebResourceTest extends ResourceTest {
47 +
48 + final AclService mockAclService = createMock(AclService.class);
49 + final AclStore mockAclStore = createMock(AclStore.class);
50 + final List<AclRule> rules = new ArrayList<>();
51 +
52 + @Before
53 + public void setUp() {
54 + expect(mockAclService.getAclRules()).andReturn(rules).anyTimes();
55 + ServiceDirectory testDirectory = new TestServiceDirectory().add(AclService.class, mockAclService)
56 + .add(AclStore.class, mockAclStore);
57 + BaseResource.setServiceDirectory(testDirectory);
58 + }
59 +
60 + @After
61 + public void tearDown() {
62 + verify(mockAclService);
63 + }
64 +
65 + /**
66 + * Mock id generator for testing.
67 + */
68 + private class MockIdGenerator implements IdGenerator {
69 + private AtomicLong nextId = new AtomicLong(0);
70 +
71 + @Override
72 + public long getNewId() {
73 + return nextId.getAndIncrement();
74 + }
75 + }
76 +
77 + @Test
78 + public void testaddRule() throws IOException {
79 + WebResource rs = resource();
80 + String response;
81 + String json;
82 + IdGenerator idGenerator = new MockIdGenerator();
83 + AclRule.bindIdGenerator(idGenerator);
84 +
85 + replay(mockAclService);
86 +
87 + // input a invalid JSON string that contains neither nw_src and nw_dst
88 + json = "{\"ipProto\":\"TCP\",\"dstTpPort\":\"80\"}";
89 + response = rs.path("add").post(String.class, json);
90 + assertThat(response, containsString("Failed! Either srcIp or dstIp must be assigned."));
91 +
92 + // input a invalid JSON string that doesn't contain CIDR mask bits
93 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.0.1\",\"dstTpPort\":\"80\",\"action\":\"DENY\"}";
94 + response = rs.path("add").post(String.class, json);
95 + assertThat(response, containsString("Malformed IPv4 prefix string: 10.0.0.1. " +
96 + "Address must take form \"x.x.x.x/y\""));
97 +
98 + // input a invalid JSON string that contains a invalid IP address
99 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.0.256/32\",\"dstTpPort\":\"80\",\"action\":\"DENY\"}";
100 + response = rs.path("add").post(String.class, json);
101 + assertThat(response, containsString("Invalid IP address string: 10.0.0.256"));
102 +
103 + // input a invalid JSON string that contains a invalid IP address
104 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.01/32\",\"dstTpPort\":\"80\",\"action\":\"DENY\"}";
105 + response = rs.path("add").post(String.class, json);
106 + assertThat(response, containsString("Invalid IP address string: 10.0.01"));
107 +
108 + // input a invalid JSON string that contains a invalid CIDR mask bits
109 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.0.1/a\",\"dstTpPort\":\"80\",\"action\":\"DENY\"}";
110 + response = rs.path("add").post(String.class, json);
111 + assertThat(response, containsString("Failed! For input string: \"a\""));
112 +
113 + // input a invalid JSON string that contains a invalid CIDR mask bits
114 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.0.1/33\",\"dstTpPort\":\"80\",\"action\":\"DENY\"}";
115 + response = rs.path("add").post(String.class, json);
116 + assertThat(response, containsString("Invalid prefix length 33. The value must be in the interval [0, 32]"));
117 +
118 + // input a invalid JSON string that contains a invalid ipProto value
119 + json = "{\"ipProto\":\"ARP\",\"srcIp\":\"10.0.0.1/32\",\"dstTpPort\":\"80\",\"action\":\"DENY\"}";
120 + response = rs.path("add").post(String.class, json);
121 + assertThat(response, containsString("ipProto must be assigned to TCP, UDP, or ICMP."));
122 +
123 + // input a invalid JSON string that contains a invalid dstTpPort value
124 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.0.1/32\",\"dstTpPort\":\"a\",\"action\":\"DENY\"}";
125 + response = rs.path("add").post(String.class, json);
126 + assertThat(response, containsString("dstTpPort must be assigned to a numerical value."));
127 +
128 + // input a invalid JSON string that contains a invalid action value
129 + json = "{\"ipProto\":\"TCP\",\"srcIp\":\"10.0.0.1/32\",\"dstTpPort\":\"80\",\"action\":\"PERMIT\"}";
130 + response = rs.path("add").post(String.class, json);
131 + assertThat(response, containsString("action must be assigned to ALLOW or DENY."));
132 + }
133 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl.web;
21 +
22 +import com.sun.jersey.test.framework.AppDescriptor;
23 +import com.sun.jersey.test.framework.JerseyTest;
24 +import com.sun.jersey.test.framework.WebAppDescriptor;
25 +
26 +import java.io.IOException;
27 +import java.net.ServerSocket;
28 +
29 +/**
30 + * Base class for REST API tests. Performs common configuration operations.
31 + */
32 +public class ResourceTest extends JerseyTest {
33 +
34 + /**
35 + * Assigns an available port for the test.
36 + *
37 + * @param defaultPort If a port cannot be determined, this one is used.
38 + * @return free port
39 + */
40 + @Override
41 + public int getPort(int defaultPort) {
42 + try {
43 + ServerSocket socket = new ServerSocket(0);
44 + socket.setReuseAddress(true);
45 + int port = socket.getLocalPort();
46 + socket.close();
47 + return port;
48 + } catch (IOException ioe) {
49 + return defaultPort;
50 + }
51 + }
52 +
53 + @Override
54 + public AppDescriptor configure() {
55 + return new WebAppDescriptor.Builder("org.onos.acl").build();
56 + }
57 +
58 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
4 + * Advisers: Keqiu Li and Heng Qi
5 + * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 + * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 + *
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
11 + *
12 + * http://www.apache.org/licenses/LICENSE-2.0
13 + *
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
19 + */
20 +package org.onos.acl.web;
21 +
22 +import com.google.common.collect.ClassToInstanceMap;
23 +import com.google.common.collect.MutableClassToInstanceMap;
24 +import org.onlab.osgi.ServiceDirectory;
25 +
26 +/**
27 + * Service directory implementation suitable for testing.
28 + */
29 +public class TestServiceDirectory implements ServiceDirectory {
30 +
31 +
32 + private ClassToInstanceMap<Object> services = MutableClassToInstanceMap.create();
33 +
34 + @Override
35 + public <T> T get(Class<T> serviceClass) {
36 + return services.getInstance(serviceClass);
37 + }
38 +
39 + /**
40 + * Adds a new service to the directory.
41 + *
42 + * @param serviceClass service class
43 + * @param service service instance
44 + * @return self
45 + */
46 + public TestServiceDirectory add(Class serviceClass, Object service) {
47 + services.putInstance(serviceClass, service);
48 + return this;
49 + }
50 +
51 +}
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
33 33
34 <modules> 34 <modules>
35 <module>aaa</module> 35 <module>aaa</module>
36 + <module>acl</module>
36 <module>fwd</module> 37 <module>fwd</module>
37 <module>mobility</module> 38 <module>mobility</module>
38 <module>proxyarp</module> 39 <module>proxyarp</module>
......