From 90baae3dcdf021bacfc526edf0eb9e9e15f1ce4c Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Mon, 24 Jul 2023 14:29:01 +0800 Subject: [PATCH] utils: fix RBD URI if credentials contains slash (#7708) --- ui/src/views/infra/AddPrimaryStorage.vue | 5 --- .../main/java/com/cloud/utils/UriUtils.java | 31 ++++++++++++------- .../java/com/cloud/utils/UriUtilsTest.java | 14 ++++++++- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/ui/src/views/infra/AddPrimaryStorage.vue b/ui/src/views/infra/AddPrimaryStorage.vue index b6f7922d797..c1c733dbb80 100644 --- a/ui/src/views/infra/AddPrimaryStorage.vue +++ b/ui/src/views/infra/AddPrimaryStorage.vue @@ -586,11 +586,6 @@ export default { }, rbdURL (monitor, pool, id, secret) { var url - /* Replace the + and / symbols by - and _ to have URL-safe base64 going to the API - It's hacky, but otherwise we'll confuse java.net.URI which splits the incoming URI - */ - secret = secret.replace(/\+/g, '-') - secret = secret.replace(/\//g, '_') if (id !== null && secret !== null) { monitor = id + ':' + secret + '@' + monitor } diff --git a/utils/src/main/java/com/cloud/utils/UriUtils.java b/utils/src/main/java/com/cloud/utils/UriUtils.java index e68b5307f0e..dffc0106e8a 100644 --- a/utils/src/main/java/com/cloud/utils/UriUtils.java +++ b/utils/src/main/java/com/cloud/utils/UriUtils.java @@ -619,21 +619,30 @@ public class UriUtils { } private static UriInfo getRbdUrlInfo(String url) { - int secondSlash = StringUtils.ordinalIndexOf(url, "/", 2); - int thirdSlash = StringUtils.ordinalIndexOf(url, "/", 3); + if (url == null || !url.toLowerCase().startsWith("rbd://")) { + throw new CloudRuntimeException("RBD URL must start with \"rbd://\""); + } + String schema = StringUtils.substring(url, 0, 6); + url = StringUtils.substring(url, 6, url.length()); int firstAt = StringUtils.indexOf(url, "@"); - int lastColon = StringUtils.lastIndexOf(url,":"); - int lastSquareBracket = StringUtils.lastIndexOf(url,"]"); - int startOfHost = Math.max(secondSlash, firstAt) + 1; - int endOfHost = lastColon < startOfHost ? (thirdSlash > 0 ? thirdSlash : url.length() + 1) : + String credentials = (firstAt == -1) ? null : StringUtils.substring(url, 0, firstAt); + String hostInfo = (firstAt == -1) ? url : StringUtils.substring(url, firstAt + 1, url.length()); + + int firstSlash = StringUtils.indexOf(hostInfo, "/"); + int lastColon = StringUtils.lastIndexOf(hostInfo,":"); + int lastSquareBracket = StringUtils.lastIndexOf(hostInfo,"]"); + int endOfHost = lastColon == -1 ? (firstSlash > 0 ? firstSlash : hostInfo.length() + 1) : (lastSquareBracket > lastColon ? lastSquareBracket + 1 : lastColon); - String storageHosts = StringUtils.substring(url, startOfHost, endOfHost); + String storageHosts = StringUtils.substring(hostInfo, 0, endOfHost); String firstHost = storageHosts.split(",")[0]; - String strBeforeHosts = StringUtils.substring(url, 0, startOfHost); - String strAfterHosts = StringUtils.substring(url, endOfHost); + String strAfterHosts = StringUtils.substring(hostInfo, endOfHost); try { - URI uri = new URI(UriUtils.encodeURIComponent(strBeforeHosts + firstHost + strAfterHosts)); - return new UriInfo(uri.getScheme(), storageHosts, uri.getPath(), uri.getUserInfo(), uri.getPort()); + URI uri = new URI(UriUtils.encodeURIComponent(schema + firstHost + strAfterHosts)); + if (credentials != null) { + credentials = credentials.replace("+", "-"); + credentials = credentials.replace("/", "_"); + } + return new UriInfo(uri.getScheme(), storageHosts, uri.getPath(), credentials, uri.getPort()); } catch (URISyntaxException e) { throw new CloudRuntimeException(url + " is not a valid uri for RBD"); } diff --git a/utils/src/test/java/com/cloud/utils/UriUtilsTest.java b/utils/src/test/java/com/cloud/utils/UriUtilsTest.java index db02e607d63..1a3ae17f584 100644 --- a/utils/src/test/java/com/cloud/utils/UriUtilsTest.java +++ b/utils/src/test/java/com/cloud/utils/UriUtilsTest.java @@ -103,10 +103,14 @@ public class UriUtilsTest { } private void testGetUriInfoInternal(String url, String host) { + testGetUriInfoInternal(url, host, url); + } + + private void testGetUriInfoInternal(String url, String host, String newUrl) { UriUtils.UriInfo uriInfo = UriUtils.getUriInfo(url); Assert.assertEquals(host, uriInfo.getStorageHost()); - Assert.assertEquals(url, uriInfo.toString()); + Assert.assertEquals(newUrl, uriInfo.toString()); } @Test @@ -122,6 +126,10 @@ public class UriUtilsTest { String url6 = String.format("rbd://%s:3300", host); String url7 = String.format("rbd://%s", host); String url8 = String.format("rbd://user@%s", host); + String url9 = String.format("rbd://cloudstack:AQD+hJxklW1RGRAAA56oHGN6d+WPDLss2b05Cw==@%s:3300/cloudstack", host); + String url10 = String.format("rbd://cloudstack:AQDlhZxkgdmiKRAA8uHt/O9jqoBp2Iwdk2MjjQ==@%s:3300/cloudstack", host); + String url11 = String.format("rbd://cloudstack:AQD-hJxklW1RGRAAA56oHGN6d-WPDLss2b05Cw==@%s:3300/cloudstack", host); + String url12 = String.format("rbd://cloudstack:AQDlhZxkgdmiKRAA8uHt_O9jqoBp2Iwdk2MjjQ==@%s:3300/cloudstack", host); testGetUriInfoInternal(url0, host); testGetUriInfoInternal(url1, host); @@ -132,6 +140,10 @@ public class UriUtilsTest { testGetUriInfoInternal(url6, host); testGetUriInfoInternal(url7, host); testGetUriInfoInternal(url8, host); + testGetUriInfoInternal(url9, host, url11); + testGetUriInfoInternal(url10, host, url12); + testGetUriInfoInternal(url11, host); + testGetUriInfoInternal(url12, host); } @Test