1818 */
1919package org .apache .cloudstack .storage .datastore .driver ;
2020
21+ import java .io .IOException ;
22+ import java .security .InvalidKeyException ;
23+ import java .security .NoSuchAlgorithmException ;
24+ import java .util .ArrayList ;
25+ import java .util .List ;
26+ import java .util .Map ;
27+
28+ import javax .crypto .KeyGenerator ;
29+ import javax .crypto .SecretKey ;
30+ import javax .inject .Inject ;
31+
32+ import org .apache .cloudstack .engine .subsystem .api .storage .DataStore ;
33+ import org .apache .cloudstack .storage .datastore .db .ObjectStoreDao ;
34+ import org .apache .cloudstack .storage .datastore .db .ObjectStoreDetailsDao ;
35+ import org .apache .cloudstack .storage .datastore .db .ObjectStoreVO ;
36+ import org .apache .cloudstack .storage .object .BaseObjectStoreDriverImpl ;
37+ import org .apache .cloudstack .storage .object .Bucket ;
38+ import org .apache .cloudstack .storage .object .BucketObject ;
39+ import org .apache .commons .codec .binary .Base64 ;
40+ import org .apache .commons .lang3 .StringUtils ;
41+ import org .apache .log4j .Logger ;
42+
2143import com .amazonaws .services .s3 .model .AccessControlList ;
2244import com .amazonaws .services .s3 .model .BucketPolicy ;
2345import com .cloud .agent .api .to .DataStoreTO ;
24- import org .apache .cloudstack .storage .object .Bucket ;
2546import com .cloud .storage .BucketVO ;
2647import com .cloud .storage .dao .BucketDao ;
2748import com .cloud .user .Account ;
2849import com .cloud .user .AccountDetailsDao ;
2950import com .cloud .user .dao .AccountDao ;
3051import com .cloud .utils .exception .CloudRuntimeException ;
52+
3153import io .minio .BucketExistsArgs ;
3254import io .minio .DeleteBucketEncryptionArgs ;
3355import io .minio .MakeBucketArgs ;
4264import io .minio .admin .messages .DataUsageInfo ;
4365import io .minio .messages .SseConfiguration ;
4466import io .minio .messages .VersioningConfiguration ;
45- import org .apache .cloudstack .engine .subsystem .api .storage .DataStore ;
46- import org .apache .cloudstack .storage .datastore .db .ObjectStoreDao ;
47- import org .apache .cloudstack .storage .datastore .db .ObjectStoreDetailsDao ;
48- import org .apache .cloudstack .storage .datastore .db .ObjectStoreVO ;
49- import org .apache .cloudstack .storage .object .BaseObjectStoreDriverImpl ;
50- import org .apache .cloudstack .storage .object .BucketObject ;
51- import org .apache .commons .codec .binary .Base64 ;
52- import org .apache .log4j .Logger ;
53-
54- import javax .crypto .KeyGenerator ;
55- import javax .crypto .SecretKey ;
56- import javax .inject .Inject ;
57- import java .security .NoSuchAlgorithmException ;
58- import java .util .ArrayList ;
59- import java .util .HashMap ;
60- import java .util .List ;
61- import java .util .Map ;
6267
6368public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
6469 private static final Logger s_logger = Logger .getLogger (MinIOObjectStoreDriverImpl .class );
70+ protected static final String ACS_PREFIX = "acs" ;
6571
6672 @ Inject
6773 AccountDao _accountDao ;
@@ -81,14 +87,18 @@ public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
8187 private static final String ACCESS_KEY = "accesskey" ;
8288 private static final String SECRET_KEY = "secretkey" ;
8389
84- private static final String MINIO_ACCESS_KEY = "minio-accesskey" ;
85- private static final String MINIO_SECRET_KEY = "minio-secretkey" ;
90+ protected static final String MINIO_ACCESS_KEY = "minio-accesskey" ;
91+ protected static final String MINIO_SECRET_KEY = "minio-secretkey" ;
8692
8793 @ Override
8894 public DataStoreTO getStoreTO (DataStore store ) {
8995 return null ;
9096 }
9197
98+ protected String getUserOrAccessKeyForAccount (Account account ) {
99+ return String .format ("%s-%s" , ACS_PREFIX , account .getUuid ());
100+ }
101+
92102 @ Override
93103 public Bucket createBucket (Bucket bucket , boolean objectLock ) {
94104 //ToDo Client pool mgmt
@@ -135,8 +145,8 @@ public Bucket createBucket(Bucket bucket, boolean objectLock) {
135145 " \" Version\" : \" 2012-10-17\" \n " +
136146 " }" ;
137147 MinioAdminClient minioAdminClient = getMinIOAdminClient (storeId );
138- String policyName = "acs-" + account . getAccountName ()+ "-policy" ;
139- String userName = "acs-" + account . getAccountName ( );
148+ String policyName = getUserOrAccessKeyForAccount ( account ) + "-policy" ;
149+ String userName = getUserOrAccessKeyForAccount ( account );
140150 try {
141151 minioAdminClient .addCannedPolicy (policyName , policy );
142152 minioAdminClient .setPolicy (userName , false , policyName );
@@ -250,22 +260,53 @@ public void deleteBucketPolicy(String bucketName, long storeId) {
250260
251261 }
252262
263+ protected void updateAccountCredentials (final long accountId , final String accessKey , final String secretKey , final boolean checkIfNotPresent ) {
264+ Map <String , String > details = _accountDetailsDao .findDetails (accountId );
265+ boolean updateNeeded = false ;
266+ if (!checkIfNotPresent || StringUtils .isBlank (details .get (MINIO_ACCESS_KEY ))) {
267+ details .put (MINIO_ACCESS_KEY , accessKey );
268+ updateNeeded = true ;
269+ }
270+ if (StringUtils .isAllBlank (secretKey , details .get (MINIO_SECRET_KEY ))) {
271+ s_logger .error (String .format ("Failed to retrieve secret key for MinIO user: %s from store and account details" , accessKey ));
272+ }
273+ if (StringUtils .isNotBlank (secretKey ) && (!checkIfNotPresent || StringUtils .isBlank (details .get (MINIO_SECRET_KEY )))) {
274+ details .put (MINIO_SECRET_KEY , secretKey );
275+ updateNeeded = true ;
276+ }
277+ if (!updateNeeded ) {
278+ return ;
279+ }
280+ _accountDetailsDao .persist (accountId , details );
281+ }
282+
253283 @ Override
254284 public boolean createUser (long accountId , long storeId ) {
255285 Account account = _accountDao .findById (accountId );
256286 MinioAdminClient minioAdminClient = getMinIOAdminClient (storeId );
257- String accessKey = "acs-" + account . getAccountName ( );
287+ String accessKey = getUserOrAccessKeyForAccount ( account );
258288 // Check user exists
259289 try {
260290 UserInfo userInfo = minioAdminClient .getUserInfo (accessKey );
261291 if (userInfo != null ) {
262- s_logger .debug ("User already exists in MinIO store: " +accessKey );
292+ if (s_logger .isDebugEnabled ()) {
293+ s_logger .debug (String .format ("Skipping user creation as the user already exists in MinIO store: %s" , accessKey ));
294+ }
295+ updateAccountCredentials (accountId , accessKey , userInfo .secretKey (), true );
263296 return true ;
264297 }
265- } catch (Exception e ) {
266- s_logger .debug ("User does not exist. Creating user: " +accessKey );
298+ } catch (NoSuchAlgorithmException | IOException | InvalidKeyException e ) {
299+ s_logger .error (String .format ("Error encountered while retrieving user: %s for existing MinIO store user check" , accessKey ), e );
300+ return false ;
301+ } catch (RuntimeException e ) { // MinIO lib may throw RuntimeException with code: XMinioAdminNoSuchUser
302+ if (s_logger .isDebugEnabled ()) {
303+ s_logger .debug (String .format ("Ignoring error encountered while retrieving user: %s for existing MinIO store user check" , accessKey ));
304+ }
305+ s_logger .trace ("Exception during MinIO user check" , e );
306+ }
307+ if (s_logger .isDebugEnabled ()) {
308+ s_logger .debug (String .format ("MinIO store user does not exist. Creating user: %s" , accessKey ));
267309 }
268-
269310 KeyGenerator generator = null ;
270311 try {
271312 generator = KeyGenerator .getInstance ("HmacSHA1" );
@@ -280,10 +321,7 @@ public boolean createUser(long accountId, long storeId) {
280321 throw new CloudRuntimeException (e );
281322 }
282323 // Store user credentials
283- Map <String , String > details = new HashMap <>();
284- details .put (MINIO_ACCESS_KEY , accessKey );
285- details .put (MINIO_SECRET_KEY , secretKey );
286- _accountDetailsDao .persist (accountId , details );
324+ updateAccountCredentials (accountId , accessKey , secretKey , false );
287325 return true ;
288326 }
289327
0 commit comments