Andrea Campanella
Committed by Gerrit Code Review

ONOS-3810 augmenting Rest southbound protocol and provider for https and password based auth

Change-Id: I3e5f07ba6a751bc8a7637373c037a1910181f9ab
...@@ -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"
......