Skip to content

Commit a24263f

Browse files
committed
CLOUDSTACK-6030: Encrypt the primary and secondary smb storage password when it is stored in the db.
1 parent 0ce4888 commit a24263f

8 files changed

Lines changed: 100 additions & 16 deletions

File tree

api/src/com/cloud/storage/Storage.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public static enum TemplateType {
8686

8787
public static enum StoragePoolType {
8888
Filesystem(false), // local directory
89-
NetworkFilesystem(true), // NFS or CIFS
89+
NetworkFilesystem(true), // NFS
9090
IscsiLUN(true), // shared LUN, with a clusterfs overlay
9191
Iscsi(true), // for e.g., ZFS Comstar
9292
ISO(false), // for iso image
@@ -97,7 +97,8 @@ public static enum StoragePoolType {
9797
VMFS(true), // VMware VMFS storage
9898
PreSetup(true), // for XenServer, Storage Pool is set up by customers.
9999
EXT(false), // XenServer local EXT SR
100-
OCFS2(true);
100+
OCFS2(true),
101+
SMB(true);
101102

102103
boolean shared;
103104

engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.cloud.storage.DataStoreRole;
3232
import com.cloud.storage.ImageStore;
3333
import com.cloud.storage.ScopeType;
34+
import com.cloud.utils.UriUtils;
3435
import com.cloud.utils.db.GenericDao;
3536

3637
@Entity
@@ -149,11 +150,18 @@ public String getUuid() {
149150
}
150151

151152
public String getUrl() {
152-
return url;
153+
String updatedUrl = url;
154+
if ("cifs".equalsIgnoreCase(this.protocol)) {
155+
updatedUrl = UriUtils.getUpdateUri(updatedUrl, false);
156+
}
157+
return updatedUrl;
153158
}
154159

155160
public void setUrl(String url) {
156161
this.url = url;
162+
if ("cifs".equalsIgnoreCase(this.protocol)) {
163+
this.url = UriUtils.getUpdateUri(url, true);
164+
}
157165
}
158166

159167
public Date getCreated() {

engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.cloud.storage.Storage.StoragePoolType;
3535
import com.cloud.storage.StoragePool;
3636
import com.cloud.storage.StoragePoolStatus;
37+
import com.cloud.utils.UriUtils;
3738
import com.cloud.utils.db.GenericDao;
3839

3940
@Entity
@@ -141,10 +142,10 @@ public StoragePoolVO(long poolId, String name, String uuid, StoragePoolType type
141142
this.usedBytes = availableBytes;
142143
this.capacityBytes = capacityBytes;
143144
this.hostAddress = hostAddress;
144-
this.path = hostPath;
145145
this.port = port;
146146
this.podId = podId;
147147
this.setStatus(StoragePoolStatus.Initial);
148+
this.setPath(hostPath);
148149
}
149150

150151
public StoragePoolVO(StoragePoolVO that) {
@@ -155,9 +156,9 @@ public StoragePoolVO(StoragePoolType type, String hostAddress, int port, String
155156
this.poolType = type;
156157
this.hostAddress = hostAddress;
157158
this.port = port;
158-
this.path = path;
159159
this.setStatus(StoragePoolStatus.Initial);
160160
this.uuid = UUID.randomUUID().toString();
161+
this.setPath(path);
161162
}
162163

163164
@Override
@@ -262,7 +263,12 @@ public void setHostAddress(String host) {
262263

263264
@Override
264265
public String getPath() {
265-
return path;
266+
String updatedPath = path;
267+
if (this.poolType == StoragePoolType.SMB) {
268+
updatedPath = UriUtils.getUpdateUri(updatedPath, false);
269+
}
270+
271+
return updatedPath;
266272
}
267273

268274
@Override
@@ -292,6 +298,9 @@ public void setUuid(String uuid) {
292298

293299
public void setPath(String path) {
294300
this.path = path;
301+
if (this.poolType == StoragePoolType.SMB) {
302+
this.path = UriUtils.getUpdateUri(this.path, true);
303+
}
295304
}
296305

297306
public void setUserInfo(String userInfo) {

engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ public DataStore createPrimaryDataStore(PrimaryDataStoreParameters params) {
7070
dataStoreVO = new StoragePoolVO();
7171
dataStoreVO.setStorageProviderName(params.getProviderName());
7272
dataStoreVO.setHostAddress(params.getHost());
73-
dataStoreVO.setPath(params.getPath());
7473
dataStoreVO.setPoolType(params.getType());
74+
dataStoreVO.setPath(params.getPath());
7575
dataStoreVO.setPort(params.getPort());
7676
dataStoreVO.setName(params.getName());
7777
dataStoreVO.setUuid(params.getUuid());

plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public string UncPath
6161
get
6262
{
6363
string uncPath = null;
64-
if (uri != null && (uri.Scheme.Equals("cifs") || uri.Scheme.Equals("networkfilesystem")))
64+
if (uri != null && (uri.Scheme.Equals("cifs") || uri.Scheme.Equals("networkfilesystem") || uri.Scheme.Equals("smb")))
6565
{
6666
uncPath = @"\\" + uri.Host + uri.LocalPath;
6767
}
@@ -584,7 +584,11 @@ public enum StoragePoolType
584584
/// <summary>
585585
///
586586
/// </summary>
587-
OCFS2
587+
OCFS2,
588+
/// <summary>
589+
/// for hyper-v
590+
/// </summary>
591+
SMB
588592
}
589593

590594
public enum StorageResourceType

plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,8 @@ public JContainer ModifyStoragePoolCommand([FromBody]dynamic cmd)
916916
GetCapacityForLocalPath(localPath, out capacityBytes, out availableBytes);
917917
hostPath = localPath;
918918
}
919-
else if (poolType == StoragePoolType.NetworkFilesystem)
919+
else if (poolType == StoragePoolType.NetworkFilesystem ||
920+
poolType == StoragePoolType.SMB)
920921
{
921922
NFSTO share = new NFSTO();
922923
String uriStr = "cifs://" + (string)cmd.pool.host + (string)cmd.pool.path;
@@ -972,7 +973,8 @@ private bool ValidateStoragePoolCommand(dynamic cmd, out string localPath, out S
972973
}
973974

974975
if (poolType != StoragePoolType.Filesystem &&
975-
poolType != StoragePoolType.NetworkFilesystem)
976+
poolType != StoragePoolType.NetworkFilesystem &&
977+
poolType != StoragePoolType.SMB)
976978
{
977979
details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd);
978980
logger.Error(details);
@@ -1815,7 +1817,7 @@ public JContainer GetStorageStatsCommand([FromBody]dynamic cmd)
18151817
used = capacity - available;
18161818
result = true;
18171819
}
1818-
else if (poolType == StoragePoolType.NetworkFilesystem)
1820+
else if (poolType == StoragePoolType.NetworkFilesystem || poolType == StoragePoolType.SMB)
18191821
{
18201822
string sharePath = config.getPrimaryStorage((string)cmd.id);
18211823
if (sharePath != null)

plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,11 @@ public DataStore initialize(Map<String, Object> dsInfos) {
203203
if (port == -1) {
204204
port = 445;
205205
}
206-
parameters.setType(StoragePoolType.NetworkFilesystem);
206+
207+
parameters.setType(StoragePoolType.SMB);
207208
parameters.setHost(storageHost);
208209
parameters.setPort(port);
209210
parameters.setPath(hostPath);
210-
parameters.setUserInfo(uri.getQuery());
211-
212211
} else if (scheme.equalsIgnoreCase("file")) {
213212
if (port == -1) {
214213
port = 0;
@@ -347,10 +346,11 @@ public DataStore initialize(Map<String, Object> dsInfos) {
347346

348347
protected boolean createStoragePool(long hostId, StoragePool pool) {
349348
s_logger.debug("creating pool " + pool.getName() + " on host " + hostId);
349+
350350
if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem &&
351351
pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS &&
352352
pool.getPoolType() != StoragePoolType.SharedMountPoint && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 &&
353-
pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) {
353+
pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM && pool.getPoolType() != StoragePoolType.SMB) {
354354
s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
355355
return false;
356356
}

utils/src/com/cloud/utils/UriUtils.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
import java.net.URISyntaxException;
2727
import java.net.URLEncoder;
2828
import java.net.UnknownHostException;
29+
import java.util.ArrayList;
2930
import java.util.List;
31+
import java.util.ListIterator;
32+
import java.util.StringTokenizer;
3033

3134
import javax.net.ssl.HttpsURLConnection;
3235

@@ -37,10 +40,14 @@
3740
import org.apache.commons.httpclient.UsernamePasswordCredentials;
3841
import org.apache.commons.httpclient.auth.AuthScope;
3942
import org.apache.commons.httpclient.methods.GetMethod;
43+
import org.apache.commons.httpclient.util.URIUtil;
4044
import org.apache.http.NameValuePair;
45+
import org.apache.http.message.BasicNameValuePair;
46+
import org.apache.http.client.utils.URIBuilder;
4147
import org.apache.http.client.utils.URLEncodedUtils;
4248
import org.apache.log4j.Logger;
4349

50+
import com.cloud.utils.crypt.DBEncryptionUtil;
4451
import com.cloud.utils.exception.CloudRuntimeException;
4552

4653
public class UriUtils {
@@ -138,6 +145,59 @@ public static boolean cifsCredentialsPresent(URI uri) {
138145
return (foundUser && foundPswd);
139146
}
140147

148+
public static String getUpdateUri(String url, boolean encrypt) {
149+
String updatedPath = null;
150+
try {
151+
String query = URIUtil.getQuery(url);
152+
URIBuilder builder = new URIBuilder(url);
153+
builder.removeQuery();
154+
155+
String updatedQuery = new String();
156+
List<NameValuePair> queryParams = getUserDetails(query);
157+
ListIterator<NameValuePair> iterator = queryParams.listIterator();
158+
while (iterator.hasNext()) {
159+
NameValuePair param = iterator.next();
160+
String value = null;
161+
if ("password".equalsIgnoreCase(param.getName()) &&
162+
param.getValue() != null) {
163+
value = encrypt ? DBEncryptionUtil.encrypt(param.getValue()) : DBEncryptionUtil.decrypt(param.getValue());
164+
} else {
165+
value = param.getValue();
166+
}
167+
168+
if (updatedQuery.isEmpty()) {
169+
updatedQuery += (param.getName() + "=" + value);
170+
} else {
171+
updatedQuery += ("&" + param.getName() + "=" + value);
172+
}
173+
}
174+
175+
String schemeAndHost = new String();
176+
URI newUri = builder.build();
177+
if (newUri.getScheme() != null) {
178+
schemeAndHost = newUri.getScheme() + "://" + newUri.getHost();
179+
}
180+
181+
updatedPath = schemeAndHost + newUri.getPath() + "?" + updatedQuery;
182+
} catch (URISyntaxException e) {
183+
throw new CloudRuntimeException("Couldn't generate an updated uri. " + e.getMessage());
184+
}
185+
186+
return updatedPath;
187+
}
188+
189+
private static List<NameValuePair> getUserDetails(String query) {
190+
List<NameValuePair> details = new ArrayList<NameValuePair>();
191+
StringTokenizer allParams = new StringTokenizer(query, "&");
192+
while (allParams.hasMoreTokens()) {
193+
String param = allParams.nextToken();
194+
details.add(new BasicNameValuePair(param.substring(0, param.indexOf("=")),
195+
param.substring(param.indexOf("=") + 1)));
196+
}
197+
198+
return details;
199+
}
200+
141201
// Get the size of a file from URL response header.
142202
public static Long getRemoteSize(String url) {
143203
Long remoteSize = (long)0;

0 commit comments

Comments
 (0)