4646import com .cloud .utils .db .Transaction ;
4747import com .cloud .utils .db .TransactionCallbackWithException ;
4848import com .cloud .utils .exception .CloudRuntimeException ;
49+ import org .apache .cloudstack .api .ApiCommandResourceType ;
4950import org .apache .cloudstack .api .command .admin .kms .MigrateVolumesToKMSCmd ;
5051import org .apache .cloudstack .api .command .user .kms .CreateKMSKeyCmd ;
5152import org .apache .cloudstack .api .command .user .kms .DeleteKMSKeyCmd ;
5657import org .apache .cloudstack .api .command .user .kms .hsm .DeleteHSMProfileCmd ;
5758import org .apache .cloudstack .api .command .user .kms .hsm .ListHSMProfilesCmd ;
5859import org .apache .cloudstack .api .command .user .kms .hsm .UpdateHSMProfileCmd ;
59- import org .apache .cloudstack .api .ApiCommandResourceType ;
6060import org .apache .cloudstack .api .response .HSMProfileResponse ;
6161import org .apache .cloudstack .api .response .KMSKeyResponse ;
6262import org .apache .cloudstack .api .response .ListResponse ;
9999public class KMSManagerImpl extends ManagerBase implements KMSManager , PluggableService {
100100 private static final Logger logger = LogManager .getLogger (KMSManagerImpl .class );
101101 private static final Map <String , KMSProvider > kmsProviderMap = new HashMap <>();
102- private final ExecutorService kmsOperationExecutor = new ThreadPoolExecutor (
103- 2 , 100 , 60L , TimeUnit .SECONDS , new SynchronousQueue <>(), r -> {
104- Thread t = new Thread (r , "kms-operation" );
105- t .setDaemon (true );
106- return t ;
107- });
102+ private ExecutorService kmsOperationExecutor ;
103+
108104 @ Inject
109105 private KMSWrappedKeyDao kmsWrappedKeyDao ;
106+
110107 @ Inject
111108 private KMSKeyDao kmsKeyDao ;
109+
112110 @ Inject
113111 private KMSKekVersionDao kmsKekVersionDao ;
112+
114113 @ Inject
115114 private HSMProfileDao hsmProfileDao ;
115+
116116 @ Inject
117117 private HSMProfileDetailsDao hsmProfileDetailsDao ;
118+
118119 @ Inject
119120 private AccountManager accountManager ;
121+
120122 @ Inject
121123 private DataCenterDao dataCenterDao ;
124+
122125 @ Inject
123126 private VolumeDao volumeDao ;
127+
124128 @ Inject
125129 private PassphraseDao passphraseDao ;
126130 private List <KMSProvider > kmsProviders ;
@@ -183,7 +187,7 @@ public void checkKmsKeyForVolumeEncryption(Account caller, Long kmsKeyId, Long z
183187 if (key .getZoneId () != null && zoneId != null && !key .getZoneId ().equals (zoneId )) {
184188 throw new InvalidParameterValueException (
185189 "KMS key belongs to zone " + key .getZoneId () +
186- " but the target resource is in zone " + zoneId );
190+ " but the target resource is in zone " + zoneId );
187191 }
188192 if (!key .isEnabled ()) {
189193 throw new InvalidParameterValueException (
@@ -252,7 +256,7 @@ public byte[] unwrapKey(Long wrappedKeyId) throws KMSException {
252256 }
253257
254258 private byte [] getUnwrappedKey (KMSWrappedKeyVO wrappedVO , KMSKeyVO kmsKey ,
255- KMSKekVersionVO version ) throws Exception {
259+ KMSKekVersionVO version ) throws Exception {
256260 HSMProfileVO hsmProfile = hsmProfileDao .findById (version .getHsmProfileId ());
257261 KMSProvider provider = getKMSProvider (hsmProfile .getProtocol ());
258262
@@ -399,7 +403,7 @@ KMSKeyResponse createKMSKeyResponse(KMSKey kmsKey) {
399403
400404 Account caller = CallContext .current ().getCallingAccount ();
401405 if (caller != null && (caller .getType () == Account .Type .ADMIN
402- || caller .getType () == Account .Type .RESOURCE_DOMAIN_ADMIN )) {
406+ || caller .getType () == Account .Type .RESOURCE_DOMAIN_ADMIN )) {
403407 response .setKekLabel (kmsKey .getKekLabel ());
404408 }
405409
@@ -408,8 +412,8 @@ KMSKeyResponse createKMSKeyResponse(KMSKey kmsKey) {
408412 }
409413
410414 KMSKey createUserKMSKey (Long accountId , Long domainId , Long zoneId ,
411- String name , String description , KeyPurpose purpose ,
412- Integer keyBits , long hsmProfileId ) throws KMSException {
415+ String name , String description , KeyPurpose purpose ,
416+ Integer keyBits , long hsmProfileId ) throws KMSException {
413417 HSMProfileVO profile = hsmProfileDao .findById (hsmProfileId );
414418 if (profile == null ) {
415419 throw KMSException .invalidParameter ("HSM Profile not found" );
@@ -480,7 +484,7 @@ public ListResponse<KMSKeyResponse> listKMSKeys(ListKMSKeysCmd cmd) {
480484 }
481485
482486 SearchBuilder <KMSKeyVO > getSearchBuilderForKMSKeys (Long domainId , Boolean isRecursive , List <Long > permittedAccounts ,
483- ListProjectResourcesCriteria listProjectResourcesCriteria ) {
487+ ListProjectResourcesCriteria listProjectResourcesCriteria ) {
484488 SearchBuilder <KMSKeyVO > sb = kmsKeyDao .createSearchBuilder ();
485489 accountManager .buildACLSearchBuilder (sb , domainId , isRecursive , permittedAccounts ,
486490 listProjectResourcesCriteria );
@@ -495,8 +499,8 @@ SearchBuilder<KMSKeyVO> getSearchBuilderForKMSKeys(Long domainId, Boolean isRecu
495499 }
496500
497501 SearchCriteria <KMSKeyVO > getSearchCriteriaForKMSKeys (SearchBuilder <KMSKeyVO > searchBuilder , ListKMSKeysCmd cmd ,
498- Long domainId , Boolean isRecursive , List <Long > permittedAccounts ,
499- ListProjectResourcesCriteria listProjectResourcesCriteria ) {
502+ Long domainId , Boolean isRecursive , List <Long > permittedAccounts ,
503+ ListProjectResourcesCriteria listProjectResourcesCriteria ) {
500504 SearchCriteria <KMSKeyVO > sc = searchBuilder .create ();
501505 accountManager .buildACLSearchCriteria (sc , domainId , isRecursive , permittedAccounts ,
502506 listProjectResourcesCriteria );
@@ -567,12 +571,12 @@ void deleteUserKMSKey(KMSKeyVO key) throws KMSException {
567571 long wrappedKeyCount = kmsWrappedKeyDao .countByKmsKeyId (key .getId ());
568572 if (wrappedKeyCount > 0 ) {
569573 throw new InvalidParameterValueException ("Cannot delete KMS key: " + key + ". " + wrappedKeyCount +
570- " wrapped key(s) still reference this key" );
574+ " wrapped key(s) still reference this key" );
571575 }
572576
573577 if (volumeDao .existsWithKmsKey (key .getId ())) {
574578 throw new InvalidParameterValueException ("Cannot delete KMS key: " + key + ". " +
575- "There are Volumes which still reference this key" );
579+ "There are Volumes which still reference this key" );
576580 }
577581
578582 List <KMSKekVersionVO > kekVersions = kmsKekVersionDao .listByKmsKeyId (key .getId ());
@@ -637,15 +641,15 @@ public String rotateKMSKey(RotateKMSKeyCmd cmd) throws KMSException {
637641 CallContext .current ().setEventDetails (String .format ("Rotated KMS key: %s (uuid: %s) from version %d to %d" , kmsKey .getName (), kmsKey .getUuid (), currentActive .getVersionNumber (), newVersion .getVersionNumber ()));
638642
639643 logger .info ("KMS key rotation initiated: {} -> new KEK version {} (UUID: {}). " +
640- "Background job will gradually rewrap {} wrapped key(s)" ,
644+ "Background job will gradually rewrap {} wrapped key(s)" ,
641645 kmsKey , newVersion .getVersionNumber (), newVersion .getUuid (),
642646 kmsWrappedKeyDao .countByKmsKeyId (kmsKey .getId ()));
643647
644648 return newVersion .getUuid ();
645649 }
646650
647651 String rotateKek (KMSKeyVO kmsKey , String oldKekLabel , String newKekLabel , int keyBits ,
648- HSMProfileVO newHSMProfile ) throws KMSException {
652+ HSMProfileVO newHSMProfile ) throws KMSException {
649653 if (StringUtils .isEmpty (oldKekLabel )) {
650654 throw KMSException .invalidParameter ("oldKekLabel must be specified" );
651655 }
@@ -662,7 +666,7 @@ String rotateKek(KMSKeyVO kmsKey, String oldKekLabel, String newKekLabel, int ke
662666 if (StringUtils .isEmpty (newKekLabel )) {
663667 List <KMSKekVersionVO > existingVersions = kmsKekVersionDao .listByKmsKeyId (kmsKey .getId ());
664668 int nextVersion = existingVersions .stream ().mapToInt (KMSKekVersionVO ::getVersionNumber ).max ().orElse (0 )
665- + 1 ;
669+ + 1 ;
666670 newKekLabel = kmsKey .getPurpose ().generateKekLabel (kmsKey .getDomainId (), kmsKey .getAccountId (),
667671 kmsKey .getUuid (), nextVersion );
668672 }
@@ -699,7 +703,7 @@ String rotateKek(KMSKeyVO kmsKey, String oldKekLabel, String newKekLabel, int ke
699703 } catch (KMSException e ) {
700704 logger .error (
701705 "Database update failed during KEK rotation for kmsKey {}. Attempting to delete orphaned KEK "
702- + "{} from provider {}" ,
706+ + "{} from provider {}" ,
703707 kmsKey , newKekId , provider .getProviderName ());
704708 try {
705709 provider .deleteKek (newKekId );
@@ -723,9 +727,9 @@ String rotateKek(KMSKeyVO kmsKey, String oldKekLabel, String newKekLabel, int ke
723727 private KMSKekVersionVO createKekVersion (KMSKekVersionVO newVersion ) throws KMSException {
724728 List <KMSKekVersionVO > existingVersions = kmsKekVersionDao .listByKmsKeyId (newVersion .getKmsKeyId ());
725729 int nextVersion = existingVersions .stream ()
726- .mapToInt (KMSKekVersionVO ::getVersionNumber )
727- .max ()
728- .orElse (0 ) + 1 ;
730+ .mapToInt (KMSKekVersionVO ::getVersionNumber )
731+ .max ()
732+ .orElse (0 ) + 1 ;
729733
730734 KMSKekVersionVO currentActive = kmsKekVersionDao .getActiveVersion (newVersion .getKmsKeyId ());
731735 if (currentActive != null ) {
@@ -853,12 +857,12 @@ public int migrateVolumesToKMS(MigrateVolumesToKMSCmd cmd) throws KMSException {
853857 }
854858
855859 private boolean migrateVolumeToKmsKey (KMSProvider provider , VolumeVO volume , KMSKey kmsKey ,
856- KMSKekVersionVO activeVersion ) {
860+ KMSKekVersionVO activeVersion ) {
857861 PassphraseVO passphrase = passphraseDao .findById (volume .getPassphraseId ());
858862 if (passphrase == null ) {
859863 logger .warn (
860864 "Skipping migration of volume from to the KMS key {} because passphrase id: {} not found for "
861- + "volume {}" ,
865+ + "volume {}" ,
862866 kmsKey , volume .getPassphraseId (), volume );
863867 return false ;
864868 }
@@ -1067,7 +1071,7 @@ public ListResponse<HSMProfileResponse> listHSMProfiles(ListHSMProfilesCmd cmd)
10671071 // If the profile is owned by the user, they should see full details even if it
10681072 // is a system profile
10691073 boolean limited = profile .getIsPublic () && !isRootAdmin && !(cmd .getIsSystem () || cmd .listAll ())
1070- && profile .getAccountId () != caller .getId ();
1074+ && profile .getAccountId () != caller .getId ();
10711075 responses .add (createHSMProfileResponse (profile , limited ));
10721076 }
10731077
@@ -1077,7 +1081,7 @@ public ListResponse<HSMProfileResponse> listHSMProfiles(ListHSMProfilesCmd cmd)
10771081 }
10781082
10791083 SearchBuilder <HSMProfileVO > getSearchBuilderForHSMProfiles (Long domainId , Boolean isRecursive ,
1080- List <Long > permittedAccounts , ListProjectResourcesCriteria listProjectResourcesCriteria ) {
1084+ List <Long > permittedAccounts , ListProjectResourcesCriteria listProjectResourcesCriteria ) {
10811085 SearchBuilder <HSMProfileVO > sb = hsmProfileDao .createSearchBuilder ();
10821086 accountManager .buildACLSearchBuilder (sb , domainId , isRecursive , permittedAccounts ,
10831087 listProjectResourcesCriteria );
@@ -1092,8 +1096,8 @@ SearchBuilder<HSMProfileVO> getSearchBuilderForHSMProfiles(Long domainId, Boolea
10921096 }
10931097
10941098 SearchCriteria <HSMProfileVO > getSearchCriteriaForHSMProfiles (SearchBuilder <HSMProfileVO > searchBuilder ,
1095- ListHSMProfilesCmd cmd , Account caller , Long domainId , Boolean isRecursive , List <Long > permittedAccounts ,
1096- ListProjectResourcesCriteria listProjectResourcesCriteria ) {
1099+ ListHSMProfilesCmd cmd , Account caller , Long domainId , Boolean isRecursive , List <Long > permittedAccounts ,
1100+ ListProjectResourcesCriteria listProjectResourcesCriteria ) {
10971101 SearchCriteria <HSMProfileVO > sc = searchBuilder .create ();
10981102
10991103 sc .setParametersIfNotNull ("id" , cmd .getId ());
@@ -1157,7 +1161,7 @@ public boolean deleteHSMProfile(DeleteHSMProfileCmd cmd) throws KMSException {
11571161 if (keyCount > 0 ) {
11581162 throw new InvalidParameterValueException (
11591163 String .format ("Cannot delete HSM profile '%s': it is referenced by %d KMS key(s). " +
1160- "Please delete or reassign those keys first." , profile .getName (), keyCount ));
1164+ "Please delete or reassign those keys first." , profile .getName (), keyCount ));
11611165 }
11621166
11631167 // Check if any KEK versions reference this HSM profile
@@ -1171,8 +1175,8 @@ public boolean deleteHSMProfile(DeleteHSMProfileCmd cmd) throws KMSException {
11711175 if (wrappedKeyCount > 0 ) {
11721176 throw new InvalidParameterValueException (
11731177 String .format ("Cannot delete HSM profile '%s': it is referenced by %d wrapped key(s) " +
1174- "through KEK versions. Please wait for key rotation to complete or delete those"
1175- + " volumes first." ,
1178+ "through KEK versions. Please wait for key rotation to complete or delete those"
1179+ + " volumes first." ,
11761180 profile .getName (), wrappedKeyCount ));
11771181 }
11781182 }
@@ -1184,10 +1188,7 @@ public boolean deleteHSMProfile(DeleteHSMProfileCmd cmd) throws KMSException {
11841188 CallContext .current ().setEventResourceType (ApiCommandResourceType .HsmProfile );
11851189 CallContext .current ().setEventDetails (String .format ("Deleted HSM profile: %s (uuid: %s)" , profile .getName (), profile .getUuid ()));
11861190
1187- if (hsmProfileDao .remove (profile .getId ())) {
1188- return true ;
1189- }
1190- return false ;
1191+ return hsmProfileDao .remove (profile .getId ());
11911192 }
11921193
11931194 @ Override
@@ -1413,6 +1414,14 @@ private void initializeKmsProviderMap() {
14131414 public boolean start () {
14141415 super .start ();
14151416 initializeKmsProviderMap ();
1417+ kmsOperationExecutor = new ThreadPoolExecutor (
1418+ KMSOperationPoolCoreSize .value (),
1419+ KMSOperationPoolMaxSize .value (),
1420+ 60L , TimeUnit .SECONDS , new SynchronousQueue <>(), r -> {
1421+ Thread t = new Thread (r , "kms-operation" );
1422+ t .setDaemon (true );
1423+ return t ;
1424+ });
14161425
14171426 for (KMSProvider provider : kmsProviderMap .values ()) {
14181427 if (provider != null ) {
@@ -1575,7 +1584,7 @@ private void processVersionRewrap(KMSKekVersionVO oldVersion, int batchSize) thr
15751584 }
15761585
15771586 void rewrapSingleKey (KMSWrappedKeyVO wrappedKeyVO , KMSKeyVO kmsKey ,
1578- KMSKekVersionVO newVersion , KMSProvider provider ) {
1587+ KMSKekVersionVO newVersion , KMSProvider provider ) {
15791588 byte [] dek = null ;
15801589 try {
15811590 dek = unwrapKey (wrappedKeyVO .getId ());
@@ -1624,7 +1633,9 @@ public ConfigKey<?>[] getConfigKeys() {
16241633 KMSRetryDelayMs ,
16251634 KMSOperationTimeoutSec ,
16261635 KMSRewrapBatchSize ,
1627- KMSRewrapIntervalMs
1636+ KMSRewrapIntervalMs ,
1637+ KMSOperationPoolCoreSize ,
1638+ KMSOperationPoolMaxSize ,
16281639 };
16291640 }
16301641
0 commit comments