Committed by
Gerrit Code Review
ONOS-3810 augmenting Rest southbound protocol and provider for https and password based auth
Change-Id: I3e5f07ba6a751bc8a7637373c037a1910181f9ab
Showing
9 changed files
with
247 additions
and
49 deletions
... | @@ -54,14 +54,20 @@ public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour | ... | @@ -54,14 +54,20 @@ public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour |
54 | private static final String NAME = "name"; | 54 | private static final String NAME = "name"; |
55 | private static final String ADMIN_STATE = "admin-state"; | 55 | private static final String ADMIN_STATE = "admin-state"; |
56 | 56 | ||
57 | - private static final ArrayList<String> LINESIDE = Lists.newArrayList( | 57 | + private static final ArrayList<String> LINESIDE_PORT_ID = Lists.newArrayList( |
58 | - "1.1", "1.2", "12.1", "12.2"); | 58 | + "4", "48"); |
59 | 59 | ||
60 | private static final String GENERAL_PORT_REQUEST = | 60 | private static final String GENERAL_PORT_REQUEST = |
61 | - "yang-api/datastore/ws-ports?config=true&format=xml&depth=unbounded"; | 61 | + "ws-ports?config=true&format=xml&depth=unbounded"; |
62 | - private static final String SPECIFIC_PORT_PATH = "yang-api/datastore/ws-ptps/ptp/"; | 62 | + private static final String SPECIFIC_PORT_PATH = "ws-ptps/ptp/"; |
63 | private static final String SPECIFIC_PORT_CONFIG = | 63 | private static final String SPECIFIC_PORT_CONFIG = |
64 | "/ptp-config?config=true&format=xml&depth=unbounded"; | 64 | "/ptp-config?config=true&format=xml&depth=unbounded"; |
65 | + //HTTP strings | ||
66 | +// private static final String GENERAL_PORT_REQUEST = | ||
67 | +// "/yang-api/datastore/ws-ports?config=true&format=xml&depth=unbounded"; | ||
68 | +// private static final String SPECIFIC_PORT_PATH = "/yang-api/datastore/ws-ptps/ptp/"; | ||
69 | +// private static final String SPECIFIC_PORT_CONFIG = | ||
70 | +// "/ptp-config?config=true&format=xml&depth=unbounded"; | ||
65 | 71 | ||
66 | 72 | ||
67 | @Override | 73 | @Override |
... | @@ -76,24 +82,35 @@ public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour | ... | @@ -76,24 +82,35 @@ public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour |
76 | loadXml(controller.get(deviceId, GENERAL_PORT_REQUEST, XML)); | 82 | loadXml(controller.get(deviceId, GENERAL_PORT_REQUEST, XML)); |
77 | List<HierarchicalConfiguration> portsConfig = | 83 | List<HierarchicalConfiguration> portsConfig = |
78 | XmlConfigParser.parseWaveServerCienaPorts(config); | 84 | XmlConfigParser.parseWaveServerCienaPorts(config); |
79 | - | ||
80 | portsConfig.stream().forEach(sub -> { | 85 | portsConfig.stream().forEach(sub -> { |
86 | + String portId = sub.getString(PORT_ID); | ||
81 | String name = sub.getString(NAME); | 87 | String name = sub.getString(NAME); |
82 | SparseAnnotations annotations = DefaultAnnotations.builder() | 88 | SparseAnnotations annotations = DefaultAnnotations.builder() |
83 | - .set(AnnotationKeys.NAME, String.valueOf(name)).build(); | 89 | + .set(AnnotationKeys.NAME, name).build(); |
84 | - if (LINESIDE.contains(name)) { | 90 | + if (LINESIDE_PORT_ID.contains(portId)) { |
85 | - String wsportInfoRequest = SPECIFIC_PORT_PATH + sub.getLong(PORT_ID) + | 91 | + String wsportInfoRequest = SPECIFIC_PORT_PATH + portId + |
86 | SPECIFIC_PORT_CONFIG; | 92 | SPECIFIC_PORT_CONFIG; |
87 | ports.add(XmlConfigParser.parseWaveServerCienaOchPorts( | 93 | ports.add(XmlConfigParser.parseWaveServerCienaOchPorts( |
88 | sub.getLong(PORT_ID), | 94 | sub.getLong(PORT_ID), |
89 | - toGbps(Long.parseLong(sub.getString(SPEED).replace(GBPS, EMPTY_STRING))), | 95 | + toGbps(Long.parseLong(sub.getString(SPEED).replace(GBPS, EMPTY_STRING) |
96 | + .replace(" ", EMPTY_STRING))), | ||
90 | XmlConfigParser.loadXml(controller.get(deviceId, wsportInfoRequest, XML)), | 97 | XmlConfigParser.loadXml(controller.get(deviceId, wsportInfoRequest, XML)), |
91 | annotations)); | 98 | annotations)); |
92 | - } else { | 99 | + //adding corresponding opposite side port |
100 | + ports.add(XmlConfigParser.parseWaveServerCienaOchPorts( | ||
101 | + sub.getLong(PORT_ID) + 1, | ||
102 | + toGbps(Long.parseLong(sub.getString(SPEED).replace(GBPS, EMPTY_STRING) | ||
103 | + .replace(" ", EMPTY_STRING))), | ||
104 | + XmlConfigParser.loadXml(controller.get(deviceId, wsportInfoRequest, XML)), | ||
105 | + DefaultAnnotations.builder() | ||
106 | + .set(AnnotationKeys.NAME, name.replace(".1", ".2")) | ||
107 | + .build())); | ||
108 | + } else if (!portId.equals("5") && !portId.equals("49")) { | ||
93 | //FIXME change when all optical types have two way information methods, see jira tickets | 109 | //FIXME change when all optical types have two way information methods, see jira tickets |
94 | final int speed100GbpsinMbps = 100000; | 110 | final int speed100GbpsinMbps = 100000; |
95 | CltSignalType cltType = toGbps(Long.parseLong( | 111 | CltSignalType cltType = toGbps(Long.parseLong( |
96 | - sub.getString(SPEED).replace(GBPS, EMPTY_STRING))) == speed100GbpsinMbps ? | 112 | + sub.getString(SPEED).replace(GBPS, EMPTY_STRING) |
113 | + .replace(" ", EMPTY_STRING))) == speed100GbpsinMbps ? | ||
97 | CltSignalType.CLT_100GBE : null; | 114 | CltSignalType.CLT_100GBE : null; |
98 | ports.add(new OduCltPortDescription(PortNumber.portNumber(sub.getLong(PORT_ID)), | 115 | ports.add(new OduCltPortDescription(PortNumber.portNumber(sub.getLong(PORT_ID)), |
99 | sub.getString(ADMIN_STATE).equals(ENABLED), | 116 | sub.getString(ADMIN_STATE).equals(ENABLED), |
... | @@ -107,5 +124,6 @@ public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour | ... | @@ -107,5 +124,6 @@ public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour |
107 | private long toGbps(long speed) { | 124 | private long toGbps(long speed) { |
108 | return speed * 1000; | 125 | return speed * 1000; |
109 | } | 126 | } |
127 | + | ||
110 | } | 128 | } |
111 | 129 | ... | ... |
... | @@ -16,7 +16,9 @@ | ... | @@ -16,7 +16,9 @@ |
16 | 16 | ||
17 | package org.onosproject.protocol.rest; | 17 | package org.onosproject.protocol.rest; |
18 | 18 | ||
19 | +import com.google.common.base.MoreObjects; | ||
19 | import com.google.common.base.Preconditions; | 20 | import com.google.common.base.Preconditions; |
21 | +import org.apache.commons.lang3.StringUtils; | ||
20 | import org.onlab.packet.IpAddress; | 22 | import org.onlab.packet.IpAddress; |
21 | import org.onosproject.net.DeviceId; | 23 | import org.onosproject.net.DeviceId; |
22 | 24 | ||
... | @@ -34,18 +36,20 @@ public class DefaultRestSBDevice implements RestSBDevice { | ... | @@ -34,18 +36,20 @@ public class DefaultRestSBDevice implements RestSBDevice { |
34 | private final String password; | 36 | private final String password; |
35 | private boolean isActive; | 37 | private boolean isActive; |
36 | private String protocol; | 38 | private String protocol; |
39 | + private String url; | ||
37 | 40 | ||
38 | public DefaultRestSBDevice(IpAddress ip, int port, String name, String password, | 41 | public DefaultRestSBDevice(IpAddress ip, int port, String name, String password, |
39 | - String protocol, boolean isActive) { | 42 | + String protocol, String url, boolean isActive) { |
40 | Preconditions.checkNotNull(ip, "IP address cannot be null"); | 43 | Preconditions.checkNotNull(ip, "IP address cannot be null"); |
41 | Preconditions.checkArgument(port > 0, "Port address cannot be negative"); | 44 | Preconditions.checkArgument(port > 0, "Port address cannot be negative"); |
42 | Preconditions.checkNotNull(protocol, "protocol address cannot be null"); | 45 | Preconditions.checkNotNull(protocol, "protocol address cannot be null"); |
43 | this.ip = ip; | 46 | this.ip = ip; |
44 | this.port = port; | 47 | this.port = port; |
45 | this.name = name; | 48 | this.name = name; |
46 | - this.password = password; | 49 | + this.password = StringUtils.isEmpty(password) ? null : password; |
47 | this.isActive = isActive; | 50 | this.isActive = isActive; |
48 | this.protocol = protocol; | 51 | this.protocol = protocol; |
52 | + this.url = StringUtils.isEmpty(url) ? null : url; | ||
49 | } | 53 | } |
50 | 54 | ||
51 | @Override | 55 | @Override |
... | @@ -89,6 +93,22 @@ public class DefaultRestSBDevice implements RestSBDevice { | ... | @@ -89,6 +93,22 @@ public class DefaultRestSBDevice implements RestSBDevice { |
89 | } | 93 | } |
90 | 94 | ||
91 | @Override | 95 | @Override |
96 | + public String url() { | ||
97 | + return url; | ||
98 | + } | ||
99 | + | ||
100 | + @Override | ||
101 | + public String toString() { | ||
102 | + return MoreObjects.toStringHelper(this) | ||
103 | + .add("url", url) | ||
104 | + .add("protocol", protocol) | ||
105 | + .add("name", name) | ||
106 | + .add("port", port) | ||
107 | + .add("ip", ip) | ||
108 | + .toString(); | ||
109 | + } | ||
110 | + | ||
111 | + @Override | ||
92 | public boolean equals(Object obj) { | 112 | public boolean equals(Object obj) { |
93 | if (obj == this) { | 113 | if (obj == this) { |
94 | return true; | 114 | return true; | ... | ... |
... | @@ -79,4 +79,10 @@ public interface RestSBDevice { | ... | @@ -79,4 +79,10 @@ public interface RestSBDevice { |
79 | */ | 79 | */ |
80 | String protocol(); | 80 | String protocol(); |
81 | 81 | ||
82 | + /** | ||
83 | + * Returns the url for the REST requests, to be used instead of IP and PORT. | ||
84 | + * | ||
85 | + * @return url | ||
86 | + */ | ||
87 | + String url(); | ||
82 | } | 88 | } | ... | ... |
... | @@ -16,17 +16,22 @@ | ... | @@ -16,17 +16,22 @@ |
16 | 16 | ||
17 | package org.onosproject.protocol.rest.ctl; | 17 | package org.onosproject.protocol.rest.ctl; |
18 | 18 | ||
19 | +import com.google.common.collect.ImmutableMap; | ||
19 | import com.sun.jersey.api.client.Client; | 20 | import com.sun.jersey.api.client.Client; |
20 | import com.sun.jersey.api.client.ClientResponse; | 21 | import com.sun.jersey.api.client.ClientResponse; |
21 | import com.sun.jersey.api.client.WebResource; | 22 | import com.sun.jersey.api.client.WebResource; |
23 | +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; | ||
22 | import org.apache.commons.io.IOUtils; | 24 | import org.apache.commons.io.IOUtils; |
23 | import org.apache.felix.scr.annotations.Activate; | 25 | import org.apache.felix.scr.annotations.Activate; |
24 | import org.apache.felix.scr.annotations.Component; | 26 | import org.apache.felix.scr.annotations.Component; |
25 | import org.apache.felix.scr.annotations.Deactivate; | 27 | import org.apache.felix.scr.annotations.Deactivate; |
26 | import org.apache.felix.scr.annotations.Service; | 28 | import org.apache.felix.scr.annotations.Service; |
27 | import org.apache.http.client.methods.HttpPatch; | 29 | import org.apache.http.client.methods.HttpPatch; |
30 | +import org.apache.http.conn.ssl.AllowAllHostnameVerifier; | ||
28 | import org.apache.http.entity.StringEntity; | 31 | import org.apache.http.entity.StringEntity; |
32 | +import org.apache.http.impl.client.CloseableHttpClient; | ||
29 | import org.apache.http.impl.client.HttpClients; | 33 | import org.apache.http.impl.client.HttpClients; |
34 | +import org.apache.http.ssl.SSLContextBuilder; | ||
30 | import org.onlab.packet.IpAddress; | 35 | import org.onlab.packet.IpAddress; |
31 | import org.onosproject.net.DeviceId; | 36 | import org.onosproject.net.DeviceId; |
32 | import org.onosproject.protocol.rest.RestSBController; | 37 | import org.onosproject.protocol.rest.RestSBController; |
... | @@ -40,6 +45,10 @@ import java.io.ByteArrayInputStream; | ... | @@ -40,6 +45,10 @@ import java.io.ByteArrayInputStream; |
40 | import java.io.IOException; | 45 | import java.io.IOException; |
41 | import java.io.InputStream; | 46 | import java.io.InputStream; |
42 | import java.nio.charset.StandardCharsets; | 47 | import java.nio.charset.StandardCharsets; |
48 | +import java.security.KeyManagementException; | ||
49 | +import java.security.KeyStoreException; | ||
50 | +import java.security.NoSuchAlgorithmException; | ||
51 | +import java.util.Base64; | ||
43 | import java.util.Map; | 52 | import java.util.Map; |
44 | import java.util.concurrent.ConcurrentHashMap; | 53 | import java.util.concurrent.ConcurrentHashMap; |
45 | 54 | ||
... | @@ -59,7 +68,9 @@ public class RestSBControllerImpl implements RestSBController { | ... | @@ -59,7 +68,9 @@ public class RestSBControllerImpl implements RestSBController { |
59 | private static final int STATUS_OK = Response.Status.OK.getStatusCode(); | 68 | private static final int STATUS_OK = Response.Status.OK.getStatusCode(); |
60 | private static final int STATUS_CREATED = Response.Status.CREATED.getStatusCode(); | 69 | private static final int STATUS_CREATED = Response.Status.CREATED.getStatusCode(); |
61 | private static final int STATUS_ACCEPTED = Response.Status.ACCEPTED.getStatusCode(); | 70 | private static final int STATUS_ACCEPTED = Response.Status.ACCEPTED.getStatusCode(); |
62 | - private static final String SLASH = "/"; | 71 | + private static final String HTTPS = "https"; |
72 | + private static final String AUTHORIZATION_PROPERTY = "authorization"; | ||
73 | + private static final String BASIC_AUTH_PREFIX = "Basic "; | ||
63 | 74 | ||
64 | private final Map<DeviceId, RestSBDevice> deviceMap = new ConcurrentHashMap<>(); | 75 | private final Map<DeviceId, RestSBDevice> deviceMap = new ConcurrentHashMap<>(); |
65 | Client client; | 76 | Client client; |
... | @@ -78,7 +89,7 @@ public class RestSBControllerImpl implements RestSBController { | ... | @@ -78,7 +89,7 @@ public class RestSBControllerImpl implements RestSBController { |
78 | 89 | ||
79 | @Override | 90 | @Override |
80 | public Map<DeviceId, RestSBDevice> getDevices() { | 91 | public Map<DeviceId, RestSBDevice> getDevices() { |
81 | - return deviceMap; | 92 | + return ImmutableMap.copyOf(deviceMap); |
82 | } | 93 | } |
83 | 94 | ||
84 | @Override | 95 | @Override |
... | @@ -88,13 +99,8 @@ public class RestSBControllerImpl implements RestSBController { | ... | @@ -88,13 +99,8 @@ public class RestSBControllerImpl implements RestSBController { |
88 | 99 | ||
89 | @Override | 100 | @Override |
90 | public RestSBDevice getDevice(IpAddress ip, int port) { | 101 | public RestSBDevice getDevice(IpAddress ip, int port) { |
91 | - for (RestSBDevice device : deviceMap.values()) { | 102 | + return deviceMap.values().stream().filter(v -> v.ip().equals(ip) |
92 | - if (device.ip().equals(ip) && | 103 | + && v.port() == port).findFirst().get(); |
93 | - device.port() == port) { | ||
94 | - return device; | ||
95 | - } | ||
96 | - } | ||
97 | - return null; | ||
98 | } | 104 | } |
99 | 105 | ||
100 | @Override | 106 | @Override |
... | @@ -162,32 +168,44 @@ public class RestSBControllerImpl implements RestSBController { | ... | @@ -162,32 +168,44 @@ public class RestSBControllerImpl implements RestSBController { |
162 | throw new IllegalArgumentException("Unsupported media type " + mediaType); | 168 | throw new IllegalArgumentException("Unsupported media type " + mediaType); |
163 | 169 | ||
164 | } | 170 | } |
165 | - return new ByteArrayInputStream(webResource.accept(type).get(ClientResponse.class) | 171 | + |
166 | - .getEntity(String.class) | 172 | + ClientResponse s = webResource.accept(type).get(ClientResponse.class); |
173 | + if (checkReply(s)) { | ||
174 | + return new ByteArrayInputStream(s.getEntity(String.class) | ||
167 | .getBytes(StandardCharsets.UTF_8)); | 175 | .getBytes(StandardCharsets.UTF_8)); |
168 | } | 176 | } |
177 | + return null; | ||
178 | + } | ||
169 | 179 | ||
170 | @Override | 180 | @Override |
171 | public boolean patch(DeviceId device, String request, InputStream payload, String mediaType) { | 181 | public boolean patch(DeviceId device, String request, InputStream payload, String mediaType) { |
172 | - String url = deviceMap.get(device).protocol() + COLON + | ||
173 | - DOUBLESLASH + | ||
174 | - deviceMap.get(device).ip().toString() + | ||
175 | - COLON + deviceMap.get(device).port() + | ||
176 | - SLASH + request; | ||
177 | try { | 182 | try { |
178 | - HttpPatch httprequest = new HttpPatch(url); | 183 | + log.debug("Url request {} ", getUrlString(device, request)); |
184 | + HttpPatch httprequest = new HttpPatch(getUrlString(device, request)); | ||
185 | + if (deviceMap.get(device).password() != null) { | ||
186 | + String userPassword = deviceMap.get(device).name() + COLON + deviceMap.get(device).password(); | ||
187 | + String base64string = Base64.getEncoder().encodeToString(userPassword.getBytes(StandardCharsets.UTF_8)); | ||
188 | + httprequest.addHeader(AUTHORIZATION_PROPERTY, BASIC_AUTH_PREFIX + base64string); | ||
189 | + } | ||
179 | if (payload != null) { | 190 | if (payload != null) { |
180 | StringEntity input = new StringEntity(IOUtils.toString(payload, StandardCharsets.UTF_8)); | 191 | StringEntity input = new StringEntity(IOUtils.toString(payload, StandardCharsets.UTF_8)); |
181 | input.setContentType(mediaType); | 192 | input.setContentType(mediaType); |
182 | httprequest.setEntity(input); | 193 | httprequest.setEntity(input); |
183 | } | 194 | } |
184 | - int responseStatusCode = HttpClients.createDefault().execute(httprequest) | 195 | + CloseableHttpClient httpClient; |
196 | + if (deviceMap.containsKey(device) && deviceMap.get(device).protocol().equals(HTTPS)) { | ||
197 | + httpClient = getApacheSslBypassClient(); | ||
198 | + } else { | ||
199 | + httpClient = HttpClients.createDefault(); | ||
200 | + } | ||
201 | + int responseStatusCode = httpClient | ||
202 | + .execute(httprequest) | ||
185 | .getStatusLine() | 203 | .getStatusLine() |
186 | .getStatusCode(); | 204 | .getStatusCode(); |
187 | return checkStatusCode(responseStatusCode); | 205 | return checkStatusCode(responseStatusCode); |
188 | - } catch (IOException e) { | 206 | + } catch (IOException | NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { |
189 | - log.error("Cannot do PATCH {} request on device {} because can't read payload", | 207 | + log.error("Cannot do PATCH {} request on device {}", |
190 | - request, device); | 208 | + request, device, e); |
191 | } | 209 | } |
192 | return false; | 210 | return false; |
193 | } | 211 | } |
... | @@ -212,11 +230,35 @@ public class RestSBControllerImpl implements RestSBController { | ... | @@ -212,11 +230,35 @@ public class RestSBControllerImpl implements RestSBController { |
212 | } | 230 | } |
213 | 231 | ||
214 | private WebResource getWebResource(DeviceId device, String request) { | 232 | private WebResource getWebResource(DeviceId device, String request) { |
215 | - return Client.create().resource(deviceMap.get(device).protocol() + COLON + | 233 | + log.debug("Sending request to URL {} ", getUrlString(device, request)); |
234 | + WebResource webResource = client.resource(getUrlString(device, request)); | ||
235 | + if (deviceMap.containsKey(device) && deviceMap.get(device).password() != null) { | ||
236 | + client.addFilter(new HTTPBasicAuthFilter(deviceMap.get(device).name(), | ||
237 | + deviceMap.get(device).password())); | ||
238 | + } | ||
239 | + return webResource; | ||
240 | + } | ||
241 | + | ||
242 | + //FIXME security issue: this trusts every SSL certificate, even if is self-signed. Also deprecated methods. | ||
243 | + private CloseableHttpClient getApacheSslBypassClient() throws NoSuchAlgorithmException, | ||
244 | + KeyManagementException, KeyStoreException { | ||
245 | + return HttpClients.custom(). | ||
246 | + setHostnameVerifier(new AllowAllHostnameVerifier()). | ||
247 | + setSslcontext(new SSLContextBuilder() | ||
248 | + .loadTrustMaterial(null, (arg0, arg1) -> true) | ||
249 | + .build()).build(); | ||
250 | + } | ||
251 | + | ||
252 | + private String getUrlString(DeviceId device, String request) { | ||
253 | + if (deviceMap.get(device).url() != null) { | ||
254 | + return deviceMap.get(device).protocol() + COLON + DOUBLESLASH | ||
255 | + + deviceMap.get(device).url() + request; | ||
256 | + } else { | ||
257 | + return deviceMap.get(device).protocol() + COLON + | ||
216 | DOUBLESLASH + | 258 | DOUBLESLASH + |
217 | deviceMap.get(device).ip().toString() + | 259 | deviceMap.get(device).ip().toString() + |
218 | - COLON + deviceMap.get(device).port() + | 260 | + COLON + deviceMap.get(device).port() + request; |
219 | - SLASH + request); | 261 | + } |
220 | } | 262 | } |
221 | 263 | ||
222 | private boolean checkReply(ClientResponse response) { | 264 | private boolean checkReply(ClientResponse response) { |
... | @@ -233,7 +275,7 @@ public class RestSBControllerImpl implements RestSBController { | ... | @@ -233,7 +275,7 @@ public class RestSBControllerImpl implements RestSBController { |
233 | statusCode == STATUS_ACCEPTED) { | 275 | statusCode == STATUS_ACCEPTED) { |
234 | return true; | 276 | return true; |
235 | } else { | 277 | } else { |
236 | - log.error("Failed request: HTTP error code : " | 278 | + log.error("Failed request, HTTP error code : " |
237 | + statusCode); | 279 | + statusCode); |
238 | return false; | 280 | return false; |
239 | } | 281 | } | ... | ... |
... | @@ -39,8 +39,8 @@ public class RestSBControllerImplTest { | ... | @@ -39,8 +39,8 @@ public class RestSBControllerImplTest { |
39 | public void setUp() { | 39 | public void setUp() { |
40 | controller = new RestSBControllerImpl(); | 40 | controller = new RestSBControllerImpl(); |
41 | controller.activate(); | 41 | controller.activate(); |
42 | - device1 = new DefaultRestSBDevice(IpAddress.valueOf("127.0.0.1"), 8080, "foo", "bar", "http", true); | 42 | + device1 = new DefaultRestSBDevice(IpAddress.valueOf("127.0.0.1"), 8080, "foo", "bar", "http", null, true); |
43 | - device2 = new DefaultRestSBDevice(IpAddress.valueOf("127.0.0.2"), 8080, "foo1", "bar2", "http", true); | 43 | + device2 = new DefaultRestSBDevice(IpAddress.valueOf("127.0.0.2"), 8080, "foo1", "bar2", "http", null, true); |
44 | controller.addDevice(device1); | 44 | controller.addDevice(device1); |
45 | } | 45 | } |
46 | 46 | ... | ... |
... | @@ -49,9 +49,14 @@ import org.onosproject.protocol.rest.RestSBController; | ... | @@ -49,9 +49,14 @@ import org.onosproject.protocol.rest.RestSBController; |
49 | import org.onosproject.protocol.rest.RestSBDevice; | 49 | import org.onosproject.protocol.rest.RestSBDevice; |
50 | import org.slf4j.Logger; | 50 | import org.slf4j.Logger; |
51 | 51 | ||
52 | +import javax.net.ssl.HttpsURLConnection; | ||
52 | import java.io.IOException; | 53 | import java.io.IOException; |
53 | import java.net.HttpURLConnection; | 54 | import java.net.HttpURLConnection; |
54 | import java.net.URL; | 55 | import java.net.URL; |
56 | +import java.nio.charset.StandardCharsets; | ||
57 | +import java.security.KeyManagementException; | ||
58 | +import java.security.NoSuchAlgorithmException; | ||
59 | +import java.util.Base64; | ||
55 | import java.util.HashSet; | 60 | import java.util.HashSet; |
56 | import java.util.Set; | 61 | import java.util.Set; |
57 | 62 | ||
... | @@ -71,6 +76,10 @@ public class RestDeviceProvider extends AbstractProvider | ... | @@ -71,6 +76,10 @@ public class RestDeviceProvider extends AbstractProvider |
71 | private static final String PROVIDER = "org.onosproject.provider.rest.device"; | 76 | private static final String PROVIDER = "org.onosproject.provider.rest.device"; |
72 | private static final String IPADDRESS = "ipaddress"; | 77 | private static final String IPADDRESS = "ipaddress"; |
73 | private static final int TEST_CONNECT_TIMEOUT = 1000; | 78 | private static final int TEST_CONNECT_TIMEOUT = 1000; |
79 | + private static final String HTTPS = "https"; | ||
80 | + private static final String AUTHORIZATION_PROPERTY = "authorization"; | ||
81 | + private static final String BASIC_AUTH_PREFIX = "Basic "; | ||
82 | + private static final String URL_SEPARATOR = "://"; | ||
74 | private final Logger log = getLogger(getClass()); | 83 | private final Logger log = getLogger(getClass()); |
75 | 84 | ||
76 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 85 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
... | @@ -202,7 +211,7 @@ public class RestDeviceProvider extends AbstractProvider | ... | @@ -202,7 +211,7 @@ public class RestDeviceProvider extends AbstractProvider |
202 | } catch (ConfigException e) { | 211 | } catch (ConfigException e) { |
203 | log.error("Configuration error {}", e); | 212 | log.error("Configuration error {}", e); |
204 | } | 213 | } |
205 | - log.info("REST Devices {}", controller.getDevices()); | 214 | + log.debug("REST Devices {}", controller.getDevices()); |
206 | controller.getDevices().keySet().forEach(deviceId -> { | 215 | controller.getDevices().keySet().forEach(deviceId -> { |
207 | DriverHandler h = driverService.createHandler(deviceId); | 216 | DriverHandler h = driverService.createHandler(deviceId); |
208 | PortDiscovery portConfig = h.behaviour(PortDiscovery.class); | 217 | PortDiscovery portConfig = h.behaviour(PortDiscovery.class); |
... | @@ -216,14 +225,39 @@ public class RestDeviceProvider extends AbstractProvider | ... | @@ -216,14 +225,39 @@ public class RestDeviceProvider extends AbstractProvider |
216 | 225 | ||
217 | private boolean testDeviceConnection(RestSBDevice device) { | 226 | private boolean testDeviceConnection(RestSBDevice device) { |
218 | try { | 227 | try { |
219 | - URL url = new URL(device.protocol(), device.ip().toString(), device.port(), "/"); | 228 | + URL url; |
220 | - HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); | 229 | + if (device.url() == null) { |
230 | + url = new URL(device.protocol(), device.ip().toString(), device.port(), ""); | ||
231 | + } else { | ||
232 | + url = new URL(device.protocol() + URL_SEPARATOR + device.url()); | ||
233 | + } | ||
234 | + HttpURLConnection urlConn; | ||
235 | + if (device.protocol().equals(HTTPS)) { | ||
236 | + //FIXME this method provides no security accepting all SSL certs. | ||
237 | + RestDeviceProviderUtilities.enableSslCert(); | ||
238 | + | ||
239 | + urlConn = (HttpsURLConnection) url.openConnection(); | ||
240 | + } else { | ||
241 | + urlConn = (HttpURLConnection) url.openConnection(); | ||
242 | + } | ||
243 | + if (device.password() != null) { | ||
244 | + String userPassword = device.name() + ":" + device.password(); | ||
245 | + String basicAuth = Base64.getEncoder() | ||
246 | + .encodeToString(userPassword.getBytes(StandardCharsets.UTF_8)); | ||
247 | + urlConn.setRequestProperty(AUTHORIZATION_PROPERTY, BASIC_AUTH_PREFIX + basicAuth); | ||
248 | + } | ||
221 | urlConn.setConnectTimeout(TEST_CONNECT_TIMEOUT); | 249 | urlConn.setConnectTimeout(TEST_CONNECT_TIMEOUT); |
222 | - boolean open = urlConn.getResponseCode() == (HttpURLConnection.HTTP_OK); | 250 | + boolean open = urlConn.getResponseCode() == (HttpsURLConnection.HTTP_OK); |
251 | + if (!open) { | ||
252 | + log.error("Device {} not accessibile, response code {} ", device, | ||
253 | + urlConn.getResponseCode()); | ||
254 | + } | ||
223 | urlConn.disconnect(); | 255 | urlConn.disconnect(); |
224 | return open; | 256 | return open; |
225 | - } catch (IOException e) { | 257 | + |
226 | - log.error("Device {} not reachable, error creating HTTP connection", device, e); | 258 | + } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) { |
259 | + log.error("Device {} not reachable, error creating {} connection", device, | ||
260 | + device.protocol(), e); | ||
227 | } | 261 | } |
228 | return false; | 262 | return false; |
229 | } | 263 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.provider.rest.device.impl; | ||
18 | + | ||
19 | +import javax.net.ssl.HttpsURLConnection; | ||
20 | +import javax.net.ssl.KeyManager; | ||
21 | +import javax.net.ssl.SSLContext; | ||
22 | +import javax.net.ssl.TrustManager; | ||
23 | +import javax.net.ssl.X509TrustManager; | ||
24 | +import java.security.KeyManagementException; | ||
25 | +import java.security.NoSuchAlgorithmException; | ||
26 | +import java.security.SecureRandom; | ||
27 | +import java.security.cert.CertificateException; | ||
28 | +import java.security.cert.X509Certificate; | ||
29 | + | ||
30 | +/** | ||
31 | + * Utilities class for RestDevice provider. | ||
32 | + */ | ||
33 | +final class RestDeviceProviderUtilities { | ||
34 | + | ||
35 | + private static final String TLS = "TLS"; | ||
36 | + | ||
37 | + //disable construction. | ||
38 | + private RestDeviceProviderUtilities(){} | ||
39 | + | ||
40 | + /** | ||
41 | + * Method that bypasses every SSL certificate verification and accepts every | ||
42 | + * connection with any SSL protected device that ONOS has an interaction with. | ||
43 | + * Needs addressing for secutirty purposes. | ||
44 | + * | ||
45 | + * @throws NoSuchAlgorithmException | ||
46 | + * @throws KeyManagementException | ||
47 | + */ | ||
48 | + //FIXME redo for security purposes. | ||
49 | + protected static void enableSslCert() throws NoSuchAlgorithmException, KeyManagementException { | ||
50 | + SSLContext ctx = SSLContext.getInstance(TLS); | ||
51 | + ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom()); | ||
52 | + SSLContext.setDefault(ctx); | ||
53 | + HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> { | ||
54 | + //FIXME better way to do this. | ||
55 | + return true; | ||
56 | + }); | ||
57 | + } | ||
58 | + | ||
59 | + //FIXME this accepts every connection | ||
60 | + private static class DefaultTrustManager implements X509TrustManager { | ||
61 | + | ||
62 | + @Override | ||
63 | + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { | ||
64 | + } | ||
65 | + | ||
66 | + @Override | ||
67 | + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { | ||
68 | + } | ||
69 | + | ||
70 | + @Override | ||
71 | + public X509Certificate[] getAcceptedIssuers() { | ||
72 | + return null; | ||
73 | + } | ||
74 | + } | ||
75 | +} |
... | @@ -42,6 +42,7 @@ public class RestProviderConfig extends Config<ApplicationId> { | ... | @@ -42,6 +42,7 @@ public class RestProviderConfig extends Config<ApplicationId> { |
42 | private static final String NAME = "name"; | 42 | private static final String NAME = "name"; |
43 | private static final String PASSWORD = "password"; | 43 | private static final String PASSWORD = "password"; |
44 | private static final String PROTOCOL = "protocol"; | 44 | private static final String PROTOCOL = "protocol"; |
45 | + private static final String URL = "url"; | ||
45 | 46 | ||
46 | public Set<RestSBDevice> getDevicesAddresses() throws ConfigException { | 47 | public Set<RestSBDevice> getDevicesAddresses() throws ConfigException { |
47 | Set<RestSBDevice> devicesAddresses = Sets.newHashSet(); | 48 | Set<RestSBDevice> devicesAddresses = Sets.newHashSet(); |
... | @@ -54,8 +55,10 @@ public class RestProviderConfig extends Config<ApplicationId> { | ... | @@ -54,8 +55,10 @@ public class RestProviderConfig extends Config<ApplicationId> { |
54 | String name = node.path(NAME).asText(); | 55 | String name = node.path(NAME).asText(); |
55 | String password = node.path(PASSWORD).asText(); | 56 | String password = node.path(PASSWORD).asText(); |
56 | String protocol = node.path(PROTOCOL).asText(); | 57 | String protocol = node.path(PROTOCOL).asText(); |
58 | + String url = node.path(URL).asText(); | ||
57 | devicesAddresses.add(new DefaultRestSBDevice(ipAddr, port, name, | 59 | devicesAddresses.add(new DefaultRestSBDevice(ipAddr, port, name, |
58 | - password, protocol, false)); | 60 | + password, protocol, |
61 | + url, false)); | ||
59 | 62 | ||
60 | } | 63 | } |
61 | } catch (IllegalArgumentException e) { | 64 | } catch (IllegalArgumentException e) { | ... | ... |
... | @@ -9,8 +9,8 @@ | ... | @@ -9,8 +9,8 @@ |
9 | "apps": { | 9 | "apps": { |
10 | "org.onosproject.restsb": { | 10 | "org.onosproject.restsb": { |
11 | "restDevices": [{ | 11 | "restDevices": [{ |
12 | - "name": "local", | 12 | + "name": "dev", |
13 | - "password": "local", | 13 | + "password": "", |
14 | "ip": "127.0.0.1", | 14 | "ip": "127.0.0.1", |
15 | "port": 8080, | 15 | "port": 8080, |
16 | "protocol": "http" | 16 | "protocol": "http" | ... | ... |
-
Please register or login to post a comment