Skip to content

Commit 5112eea

Browse files
committed
directly create the key in the store
1 parent 70564e8 commit 5112eea

File tree

9 files changed

+276
-224
lines changed

9 files changed

+276
-224
lines changed

api/src/main/java/org/apache/cloudstack/api/command/user/kms/hsm/AddHSMProfileCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
@APICommand(name = "addHSMProfile", description = "Adds a new HSM profile", responseObject = HSMProfileResponse.class,
4949
requestHasSensitiveInfo = true, responseHasSensitiveInfo = true, since = "4.23.0",
50-
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
50+
authorized = { RoleType.Admin })
5151
public class AddHSMProfileCmd extends BaseCmd {
5252

5353
@Inject

api/src/main/java/org/apache/cloudstack/api/command/user/kms/hsm/DeleteHSMProfileCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
@APICommand(name = "deleteHSMProfile", description = "Deletes an HSM profile", responseObject = SuccessResponse.class,
4242
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.23.0",
43-
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
43+
authorized = { RoleType.Admin })
4444
public class DeleteHSMProfileCmd extends BaseCmd {
4545

4646
@Inject

api/src/main/java/org/apache/cloudstack/api/command/user/kms/hsm/UpdateHSMProfileCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
@APICommand(name = "updateHSMProfile", description = "Updates an HSM profile",
4141
responseObject = HSMProfileResponse.class,
4242
requestHasSensitiveInfo = true, responseHasSensitiveInfo = true, since = "4.23.0",
43-
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
43+
authorized = { RoleType.Admin })
4444
public class UpdateHSMProfileCmd extends BaseCmd {
4545

4646
@Inject

engine/schema/src/main/java/org/apache/cloudstack/kms/KMSWrappedKeyVO.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,7 @@ public void setRemoved(Date removed) {
170170

171171
@Override
172172
public String toString() {
173-
return String.format("KMSWrappedKey %s",
174-
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
175-
this, "id", "uuid", "kmsKeyId", "kekVersionId", "accountId", "zoneId", "state", "created",
176-
"removed"));
173+
return String.format("KMSWrappedKey %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
174+
this, "id", "uuid", "kmsKeyId", "kekVersionId", "zoneId", "created", "removed"));
177175
}
178176
}

framework/kms/src/main/java/org/apache/cloudstack/framework/kms/KMSProvider.java

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,36 @@
3737
public interface KMSProvider extends Configurable, Adapter {
3838

3939
/**
40-
* Get the unique name of this provider
40+
* Returns {@code true} if the given HSM profile configuration key name refers
41+
* to a
42+
* sensitive value (PIN, password, secret, or private key) that must be
43+
* encrypted at
44+
* rest and masked in API responses.
4145
*
42-
* @return provider name (e.g., "database", "pkcs11")
46+
* <p>
47+
* This is a shared naming-convention helper used by both KMS providers (when
48+
* loading/storing profile details) and the KMS manager (when building API
49+
* responses).
50+
*
51+
* @param key configuration key name (case-insensitive); null returns false
52+
* @return true if the key is considered sensitive
4353
*/
44-
String getProviderName();
54+
static boolean isSensitiveKey(String key) {
55+
if (key == null) {
56+
return false;
57+
}
58+
return key.equalsIgnoreCase("pin") ||
59+
key.equalsIgnoreCase("password") ||
60+
key.toLowerCase().contains("secret") ||
61+
key.equalsIgnoreCase("private_key");
62+
}
4563

4664
/**
47-
* Create a new Key Encryption Key (KEK) in the secure backend with explicit HSM profile.
65+
* Get the unique name of this provider
4866
*
49-
* @param purpose the purpose/scope for this KEK
50-
* @param label human-readable label for the KEK (must be unique within purpose)
51-
* @param keyBits key size in bits (typically 128, 192, or 256)
52-
* @param hsmProfileId optional HSM profile ID to create the KEK in (null for auto-resolution/default)
53-
* @return the KEK identifier (label or handle) for later reference
54-
* @throws KMSException if KEK creation fails
67+
* @return provider name (e.g., "database", "pkcs11")
5568
*/
56-
String createKek(KeyPurpose purpose, String label, int keyBits, Long hsmProfileId) throws KMSException;
69+
String getProviderName();
5770

5871
/**
5972
* Create a new Key Encryption Key (KEK) in the secure backend.
@@ -69,6 +82,18 @@ default String createKek(KeyPurpose purpose, String label, int keyBits) throws K
6982
return createKek(purpose, label, keyBits, null);
7083
}
7184

85+
/**
86+
* Create a new Key Encryption Key (KEK) in the secure backend with explicit HSM profile.
87+
*
88+
* @param purpose the purpose/scope for this KEK
89+
* @param label human-readable label for the KEK (must be unique within purpose)
90+
* @param keyBits key size in bits (typically 128, 192, or 256)
91+
* @param hsmProfileId optional HSM profile ID to create the KEK in (null for auto-resolution/default)
92+
* @return the KEK identifier (label or handle) for later reference
93+
* @throws KMSException if KEK creation fails
94+
*/
95+
String createKek(KeyPurpose purpose, String label, int keyBits, Long hsmProfileId) throws KMSException;
96+
7297
/**
7398
* Delete a KEK from the secure backend.
7499
* WARNING: This will make all DEKs wrapped by this KEK unrecoverable.
@@ -78,7 +103,6 @@ default String createKek(KeyPurpose purpose, String label, int keyBits) throws K
78103
*/
79104
void deleteKek(String kekId) throws KMSException;
80105

81-
82106
/**
83107
* Check if a KEK exists and is accessible
84108
*
@@ -88,18 +112,6 @@ default String createKek(KeyPurpose purpose, String label, int keyBits) throws K
88112
*/
89113
boolean isKekAvailable(String kekId) throws KMSException;
90114

91-
/**
92-
* Wrap (encrypt) a plaintext Data Encryption Key with a KEK using explicit HSM profile.
93-
*
94-
* @param plainDek the plaintext DEK to wrap (caller must zeroize after call)
95-
* @param purpose the intended purpose of this DEK
96-
* @param kekLabel the label of the KEK to use for wrapping
97-
* @param hsmProfileId optional HSM profile ID to use (null for auto-resolution/default)
98-
* @return WrappedKey containing the encrypted DEK and metadata
99-
* @throws KMSException if wrapping fails or KEK not found
100-
*/
101-
WrappedKey wrapKey(byte[] plainDek, KeyPurpose purpose, String kekLabel, Long hsmProfileId) throws KMSException;
102-
103115
/**
104116
* Wrap (encrypt) a plaintext Data Encryption Key with a KEK.
105117
* Delegates to {@link #wrapKey(byte[], KeyPurpose, String, Long)} with null profile ID.
@@ -115,16 +127,16 @@ default WrappedKey wrapKey(byte[] plainDek, KeyPurpose purpose, String kekLabel)
115127
}
116128

117129
/**
118-
* Unwrap (decrypt) a wrapped DEK to obtain the plaintext key using explicit HSM profile.
119-
* <p>
120-
* SECURITY: Caller MUST zeroize the returned byte array after use
130+
* Wrap (encrypt) a plaintext Data Encryption Key with a KEK using explicit HSM profile.
121131
*
122-
* @param wrappedKey the wrapped key to decrypt
132+
* @param plainDek the plaintext DEK to wrap (caller must zeroize after call)
133+
* @param purpose the intended purpose of this DEK
134+
* @param kekLabel the label of the KEK to use for wrapping
123135
* @param hsmProfileId optional HSM profile ID to use (null for auto-resolution/default)
124-
* @return plaintext DEK (caller must zeroize!)
125-
* @throws KMSException if unwrapping fails or KEK not found
136+
* @return WrappedKey containing the encrypted DEK and metadata
137+
* @throws KMSException if wrapping fails or KEK not found
126138
*/
127-
byte[] unwrapKey(WrappedKey wrappedKey, Long hsmProfileId) throws KMSException;
139+
WrappedKey wrapKey(byte[] plainDek, KeyPurpose purpose, String kekLabel, Long hsmProfileId) throws KMSException;
128140

129141
/**
130142
* Unwrap (decrypt) a wrapped DEK to obtain the plaintext key.
@@ -141,18 +153,16 @@ default byte[] unwrapKey(WrappedKey wrappedKey) throws KMSException {
141153
}
142154

143155
/**
144-
* Generate a new random DEK and immediately wrap it with a KEK using explicit HSM profile.
145-
* (convenience method combining generation + wrapping)
156+
* Unwrap (decrypt) a wrapped DEK to obtain the plaintext key using explicit HSM profile.
157+
* <p>
158+
* SECURITY: Caller MUST zeroize the returned byte array after use
146159
*
147-
* @param purpose the intended purpose of the new DEK
148-
* @param kekLabel the label of the KEK to use for wrapping
149-
* @param keyBits DEK size in bits (typically 128, 192, or 256)
160+
* @param wrappedKey the wrapped key to decrypt
150161
* @param hsmProfileId optional HSM profile ID to use (null for auto-resolution/default)
151-
* @return WrappedKey containing the newly generated and wrapped DEK
152-
* @throws KMSException if generation or wrapping fails
162+
* @return plaintext DEK (caller must zeroize!)
163+
* @throws KMSException if unwrapping fails or KEK not found
153164
*/
154-
WrappedKey generateAndWrapDek(KeyPurpose purpose, String kekLabel, int keyBits,
155-
Long hsmProfileId) throws KMSException;
165+
byte[] unwrapKey(WrappedKey wrappedKey, Long hsmProfileId) throws KMSException;
156166

157167
/**
158168
* Generate a new random DEK and immediately wrap it with a KEK.
@@ -170,16 +180,18 @@ default WrappedKey generateAndWrapDek(KeyPurpose purpose, String kekLabel, int k
170180
}
171181

172182
/**
173-
* Rewrap a DEK with a different KEK (used during key rotation) using explicit target HSM profile.
174-
* This unwraps with the old KEK and wraps with the new KEK without exposing the plaintext DEK.
183+
* Generate a new random DEK and immediately wrap it with a KEK using explicit HSM profile.
184+
* (convenience method combining generation + wrapping)
175185
*
176-
* @param oldWrappedKey the currently wrapped key
177-
* @param newKekLabel the label of the new KEK to wrap with
178-
* @param targetHsmProfileId optional target HSM profile ID to wrap with (null for auto-resolution/default)
179-
* @return new WrappedKey encrypted with the new KEK
180-
* @throws KMSException if rewrapping fails
186+
* @param purpose the intended purpose of the new DEK
187+
* @param kekLabel the label of the KEK to use for wrapping
188+
* @param keyBits DEK size in bits (typically 128, 192, or 256)
189+
* @param hsmProfileId optional HSM profile ID to use (null for auto-resolution/default)
190+
* @return WrappedKey containing the newly generated and wrapped DEK
191+
* @throws KMSException if generation or wrapping fails
181192
*/
182-
WrappedKey rewrapKey(WrappedKey oldWrappedKey, String newKekLabel, Long targetHsmProfileId) throws KMSException;
193+
WrappedKey generateAndWrapDek(KeyPurpose purpose, String kekLabel, int keyBits,
194+
Long hsmProfileId) throws KMSException;
183195

184196
/**
185197
* Rewrap a DEK with a different KEK (used during key rotation).
@@ -195,6 +207,18 @@ default WrappedKey rewrapKey(WrappedKey oldWrappedKey, String newKekLabel) throw
195207
return rewrapKey(oldWrappedKey, newKekLabel, null);
196208
}
197209

210+
/**
211+
* Rewrap a DEK with a different KEK (used during key rotation) using explicit target HSM profile.
212+
* This unwraps with the old KEK and wraps with the new KEK without exposing the plaintext DEK.
213+
*
214+
* @param oldWrappedKey the currently wrapped key
215+
* @param newKekLabel the label of the new KEK to wrap with
216+
* @param targetHsmProfileId optional target HSM profile ID to wrap with (null for auto-resolution/default)
217+
* @return new WrappedKey encrypted with the new KEK
218+
* @throws KMSException if rewrapping fails
219+
*/
220+
WrappedKey rewrapKey(WrappedKey oldWrappedKey, String newKekLabel, Long targetHsmProfileId) throws KMSException;
221+
198222
/**
199223
* Perform health check on the provider backend
200224
*

0 commit comments

Comments
 (0)