CLOUDSTACK-6030: Encrypt the primary and secondary smb storage password when it is stored in the db.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a24263fe Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a24263fe Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a24263fe Branch: refs/heads/rbac Commit: a24263fe81dc2a173bd06e8cec6bbe43c625e9e6 Parents: 0ce4888 Author: Devdeep Singh <devd...@gmail.com> Authored: Wed Feb 5 14:58:12 2014 +0530 Committer: Devdeep Singh <devd...@gmail.com> Committed: Wed Feb 5 15:44:09 2014 +0530 ---------------------------------------------------------------------- api/src/com/cloud/storage/Storage.java | 5 +- .../storage/datastore/db/ImageStoreVO.java | 10 +++- .../storage/datastore/db/StoragePoolVO.java | 15 ++++- .../datastore/PrimaryDataStoreHelper.java | 2 +- .../HypervResource/CloudStackTypes.cs | 8 ++- .../HypervResource/HypervResourceController.cs | 8 ++- ...CloudStackPrimaryDataStoreLifeCycleImpl.java | 8 +-- utils/src/com/cloud/utils/UriUtils.java | 60 ++++++++++++++++++++ 8 files changed, 100 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/api/src/com/cloud/storage/Storage.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/storage/Storage.java b/api/src/com/cloud/storage/Storage.java index 2175c9b..ff83dfc 100755 --- a/api/src/com/cloud/storage/Storage.java +++ b/api/src/com/cloud/storage/Storage.java @@ -86,7 +86,7 @@ public class Storage { public static enum StoragePoolType { Filesystem(false), // local directory - NetworkFilesystem(true), // NFS or CIFS + NetworkFilesystem(true), // NFS IscsiLUN(true), // shared LUN, with a clusterfs overlay Iscsi(true), // for e.g., ZFS Comstar ISO(false), // for iso image @@ -97,7 +97,8 @@ public class Storage { VMFS(true), // VMware VMFS storage PreSetup(true), // for XenServer, Storage Pool is set up by customers. EXT(false), // XenServer local EXT SR - OCFS2(true); + OCFS2(true), + SMB(true); boolean shared; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java index 77e50bd..36cc57c 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java @@ -31,6 +31,7 @@ import javax.persistence.TableGenerator; import com.cloud.storage.DataStoreRole; import com.cloud.storage.ImageStore; import com.cloud.storage.ScopeType; +import com.cloud.utils.UriUtils; import com.cloud.utils.db.GenericDao; @Entity @@ -149,11 +150,18 @@ public class ImageStoreVO implements ImageStore { } public String getUrl() { - return url; + String updatedUrl = url; + if ("cifs".equalsIgnoreCase(this.protocol)) { + updatedUrl = UriUtils.getUpdateUri(updatedUrl, false); + } + return updatedUrl; } public void setUrl(String url) { this.url = url; + if ("cifs".equalsIgnoreCase(this.protocol)) { + this.url = UriUtils.getUpdateUri(url, true); + } } public Date getCreated() { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java index ede2b97..e1e21e1 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java @@ -34,6 +34,7 @@ import com.cloud.storage.ScopeType; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; +import com.cloud.utils.UriUtils; import com.cloud.utils.db.GenericDao; @Entity @@ -141,10 +142,10 @@ public class StoragePoolVO implements StoragePool { this.usedBytes = availableBytes; this.capacityBytes = capacityBytes; this.hostAddress = hostAddress; - this.path = hostPath; this.port = port; this.podId = podId; this.setStatus(StoragePoolStatus.Initial); + this.setPath(hostPath); } public StoragePoolVO(StoragePoolVO that) { @@ -155,9 +156,9 @@ public class StoragePoolVO implements StoragePool { this.poolType = type; this.hostAddress = hostAddress; this.port = port; - this.path = path; this.setStatus(StoragePoolStatus.Initial); this.uuid = UUID.randomUUID().toString(); + this.setPath(path); } @Override @@ -262,7 +263,12 @@ public class StoragePoolVO implements StoragePool { @Override public String getPath() { - return path; + String updatedPath = path; + if (this.poolType == StoragePoolType.SMB) { + updatedPath = UriUtils.getUpdateUri(updatedPath, false); + } + + return updatedPath; } @Override @@ -292,6 +298,9 @@ public class StoragePoolVO implements StoragePool { public void setPath(String path) { this.path = path; + if (this.poolType == StoragePoolType.SMB) { + this.path = UriUtils.getUpdateUri(this.path, true); + } } public void setUserInfo(String userInfo) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java index 21cefb7..9912842 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java @@ -70,8 +70,8 @@ public class PrimaryDataStoreHelper { dataStoreVO = new StoragePoolVO(); dataStoreVO.setStorageProviderName(params.getProviderName()); dataStoreVO.setHostAddress(params.getHost()); - dataStoreVO.setPath(params.getPath()); dataStoreVO.setPoolType(params.getType()); + dataStoreVO.setPath(params.getPath()); dataStoreVO.setPort(params.getPort()); dataStoreVO.setName(params.getName()); dataStoreVO.setUuid(params.getUuid()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs index c336a38..c2421ef 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs @@ -61,7 +61,7 @@ namespace HypervResource get { string uncPath = null; - if (uri != null && (uri.Scheme.Equals("cifs") || uri.Scheme.Equals("networkfilesystem"))) + if (uri != null && (uri.Scheme.Equals("cifs") || uri.Scheme.Equals("networkfilesystem") || uri.Scheme.Equals("smb"))) { uncPath = @"\\" + uri.Host + uri.LocalPath; } @@ -584,7 +584,11 @@ namespace HypervResource /// <summary> /// /// </summary> - OCFS2 + OCFS2, + /// <summary> + /// for hyper-v + /// </summary> + SMB } public enum StorageResourceType http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs index ebb3bce..718ef05 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs @@ -916,7 +916,8 @@ namespace HypervResource GetCapacityForLocalPath(localPath, out capacityBytes, out availableBytes); hostPath = localPath; } - else if (poolType == StoragePoolType.NetworkFilesystem) + else if (poolType == StoragePoolType.NetworkFilesystem || + poolType == StoragePoolType.SMB) { NFSTO share = new NFSTO(); String uriStr = "cifs://" + (string)cmd.pool.host + (string)cmd.pool.path; @@ -972,7 +973,8 @@ namespace HypervResource } if (poolType != StoragePoolType.Filesystem && - poolType != StoragePoolType.NetworkFilesystem) + poolType != StoragePoolType.NetworkFilesystem && + poolType != StoragePoolType.SMB) { details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd); logger.Error(details); @@ -1815,7 +1817,7 @@ namespace HypervResource used = capacity - available; result = true; } - else if (poolType == StoragePoolType.NetworkFilesystem) + else if (poolType == StoragePoolType.NetworkFilesystem || poolType == StoragePoolType.SMB) { string sharePath = config.getPrimaryStorage((string)cmd.id); if (sharePath != null) http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java ---------------------------------------------------------------------- diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java index 7da36b0..37861b4 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java @@ -203,12 +203,11 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore if (port == -1) { port = 445; } - parameters.setType(StoragePoolType.NetworkFilesystem); + + parameters.setType(StoragePoolType.SMB); parameters.setHost(storageHost); parameters.setPort(port); parameters.setPath(hostPath); - parameters.setUserInfo(uri.getQuery()); - } else if (scheme.equalsIgnoreCase("file")) { if (port == -1) { port = 0; @@ -347,10 +346,11 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore protected boolean createStoragePool(long hostId, StoragePool pool) { s_logger.debug("creating pool " + pool.getName() + " on host " + hostId); + if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && - pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) { + pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM && pool.getPoolType() != StoragePoolType.SMB) { s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType()); return false; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a24263fe/utils/src/com/cloud/utils/UriUtils.java ---------------------------------------------------------------------- diff --git a/utils/src/com/cloud/utils/UriUtils.java b/utils/src/com/cloud/utils/UriUtils.java index 1d5a513..2e771ae 100644 --- a/utils/src/com/cloud/utils/UriUtils.java +++ b/utils/src/com/cloud/utils/UriUtils.java @@ -26,7 +26,10 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.List; +import java.util.ListIterator; +import java.util.StringTokenizer; import javax.net.ssl.HttpsURLConnection; @@ -37,10 +40,14 @@ import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.util.URIUtil; import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.log4j.Logger; +import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.exception.CloudRuntimeException; public class UriUtils { @@ -138,6 +145,59 @@ public class UriUtils { return (foundUser && foundPswd); } + public static String getUpdateUri(String url, boolean encrypt) { + String updatedPath = null; + try { + String query = URIUtil.getQuery(url); + URIBuilder builder = new URIBuilder(url); + builder.removeQuery(); + + String updatedQuery = new String(); + List<NameValuePair> queryParams = getUserDetails(query); + ListIterator<NameValuePair> iterator = queryParams.listIterator(); + while (iterator.hasNext()) { + NameValuePair param = iterator.next(); + String value = null; + if ("password".equalsIgnoreCase(param.getName()) && + param.getValue() != null) { + value = encrypt ? DBEncryptionUtil.encrypt(param.getValue()) : DBEncryptionUtil.decrypt(param.getValue()); + } else { + value = param.getValue(); + } + + if (updatedQuery.isEmpty()) { + updatedQuery += (param.getName() + "=" + value); + } else { + updatedQuery += ("&" + param.getName() + "=" + value); + } + } + + String schemeAndHost = new String(); + URI newUri = builder.build(); + if (newUri.getScheme() != null) { + schemeAndHost = newUri.getScheme() + "://" + newUri.getHost(); + } + + updatedPath = schemeAndHost + newUri.getPath() + "?" + updatedQuery; + } catch (URISyntaxException e) { + throw new CloudRuntimeException("Couldn't generate an updated uri. " + e.getMessage()); + } + + return updatedPath; + } + + private static List<NameValuePair> getUserDetails(String query) { + List<NameValuePair> details = new ArrayList<NameValuePair>(); + StringTokenizer allParams = new StringTokenizer(query, "&"); + while (allParams.hasMoreTokens()) { + String param = allParams.nextToken(); + details.add(new BasicNameValuePair(param.substring(0, param.indexOf("=")), + param.substring(param.indexOf("=") + 1))); + } + + return details; + } + // Get the size of a file from URL response header. public static Long getRemoteSize(String url) { Long remoteSize = (long)0;