Skip to content

Commit 74f88a1

Browse files
mgmt, AKS, support disk encryption set (Azure#27768)
* support disk encryption set in AKS * extract common test base for disk encryption set * add test case * modify TestBase to enable record/replace for vault/storage * fix key/secret client version at 7.2
1 parent dee2e0b commit 74f88a1

File tree

11 files changed

+3214
-127
lines changed

11 files changed

+3214
-127
lines changed

sdk/resourcemanager/azure-resourcemanager-containerservice/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Supported disabling Kubernetes Role-Based Access Control for `KubernetesCluster` during create.
88
- Supported enabling Azure AD integration for `KubernetesCluster`.
99
- Supported disabling local accounts for `KubernetesCluster`.
10+
- Supported disk encryption set for `KubernetesCluster`.
1011

1112
### Other Changes
1213

sdk/resourcemanager/azure-resourcemanager-containerservice/src/main/java/com/azure/resourcemanager/containerservice/implementation/KubernetesClusterImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ public boolean isAzureRbacEnabled() {
262262
&& ResourceManagerUtils.toPrimitiveBoolean(innerModel().aadProfile().enableAzureRbac());
263263
}
264264

265+
@Override
266+
public String diskEncryptionSetId() {
267+
return innerModel().diskEncryptionSetId();
268+
}
269+
265270
@Override
266271
public void start() {
267272
this.startAsync().block();
@@ -546,6 +551,12 @@ public KubernetesCluster.DefinitionStages.WithCreate disableKubernetesRbac() {
546551
return this;
547552
}
548553

554+
@Override
555+
public KubernetesCluster.DefinitionStages.WithCreate withDiskEncryptionSet(String diskEncryptionSetId) {
556+
this.innerModel().withDiskEncryptionSetId(diskEncryptionSetId);
557+
return this;
558+
}
559+
549560
private static final class PrivateLinkResourceImpl implements PrivateLinkResource {
550561
private final PrivateLinkResourceInner innerModel;
551562

sdk/resourcemanager/azure-resourcemanager-containerservice/src/main/java/com/azure/resourcemanager/containerservice/models/KubernetesCluster.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ public interface KubernetesCluster
110110
/** @return whether Azure Role-Based Access Control for Kubernetes authorization is enabled. */
111111
boolean isAzureRbacEnabled();
112112

113+
/** @return resource ID of the disk encryption set. */
114+
String diskEncryptionSetId();
115+
113116
// Actions
114117

115118
/**
@@ -517,6 +520,17 @@ interface WithLocalAccounts {
517520
WithCreate disableLocalAccounts();
518521
}
519522

523+
/** The stage of the Kubernetes cluster definition allowing to specify disk encryption. */
524+
interface WithDiskEncryption {
525+
/**
526+
* Specifies the disk encryption set for the disk in cluster.
527+
*
528+
* @param diskEncryptionSetId the ID of disk encryption set.
529+
* @return the next stage of the definition
530+
*/
531+
WithCreate withDiskEncryptionSet(String diskEncryptionSetId);;
532+
}
533+
520534
/**
521535
* The stage of the definition which contains all the minimum required inputs for the resource to be created,
522536
* but also allows for any other optional settings to be specified.
@@ -533,6 +547,7 @@ interface WithCreate
533547
WithRBAC,
534548
WithAAD,
535549
WithLocalAccounts,
550+
WithDiskEncryption,
536551
Resource.DefinitionWithTags<WithCreate> {
537552
}
538553
}

sdk/resourcemanager/azure-resourcemanager-keyvault/src/main/java/com/azure/resourcemanager/keyvault/implementation/KeyImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
1313
import com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient;
1414
import com.azure.security.keyvault.keys.cryptography.CryptographyClientBuilder;
15+
import com.azure.security.keyvault.keys.cryptography.CryptographyServiceVersion;
1516
import com.azure.security.keyvault.keys.cryptography.models.DecryptResult;
1617
import com.azure.security.keyvault.keys.cryptography.models.EncryptResult;
1718
import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm;
@@ -84,6 +85,7 @@ private void init(boolean createNewCryptographyClient) {
8485
new CryptographyClientBuilder()
8586
.keyIdentifier(innerModel().getId())
8687
.pipeline(vault.vaultHttpPipeline())
88+
.serviceVersion(CryptographyServiceVersion.V7_2)
8789
.buildAsyncClient();
8890
}
8991
}

sdk/resourcemanager/azure-resourcemanager-keyvault/src/main/java/com/azure/resourcemanager/keyvault/implementation/VaultImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
4040
import com.azure.security.keyvault.keys.KeyAsyncClient;
4141
import com.azure.security.keyvault.keys.KeyClientBuilder;
42+
import com.azure.security.keyvault.keys.KeyServiceVersion;
4243
import com.azure.security.keyvault.secrets.SecretAsyncClient;
4344
import com.azure.security.keyvault.secrets.SecretClientBuilder;
45+
import com.azure.security.keyvault.secrets.SecretServiceVersion;
4446
import reactor.core.publisher.Mono;
4547

4648
import java.util.ArrayList;
@@ -89,11 +91,13 @@ private void init() {
8991
new SecretClientBuilder()
9092
.vaultUrl(vaultUrl)
9193
.pipeline(vaultHttpPipeline)
94+
.serviceVersion(SecretServiceVersion.V7_2)
9295
.buildAsyncClient();
9396
this.keyClient =
9497
new KeyClientBuilder()
9598
.vaultUrl(vaultUrl)
9699
.pipeline(vaultHttpPipeline)
100+
.serviceVersion(KeyServiceVersion.V7_2)
97101
.buildAsyncClient();
98102
}
99103
}

sdk/resourcemanager/azure-resourcemanager-test/src/main/java/com/azure/resourcemanager/test/ResourceManagerTestBase.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import java.util.HashMap;
5656
import java.util.List;
5757
import java.util.Map;
58+
import java.util.regex.Pattern;
5859
import java.util.stream.Collectors;
5960

6061
/**
@@ -288,8 +289,14 @@ protected void beforeTest() {
288289

289290
textReplacementRules.put(testProfile.getSubscriptionId(), ZERO_SUBSCRIPTION);
290291
textReplacementRules.put(testProfile.getTenantId(), ZERO_TENANT);
291-
textReplacementRules.put(AzureEnvironment.AZURE.getResourceManagerEndpoint(), PLAYBACK_URI + "/");
292-
textReplacementRules.put(AzureEnvironment.AZURE.getMicrosoftGraphEndpoint(), PLAYBACK_URI + "/");
292+
// ARM endpoint
293+
textReplacementRules.put(Pattern.quote(AzureEnvironment.AZURE.getResourceManagerEndpoint()), PLAYBACK_URI + "/");
294+
// MSGraph endpoint
295+
textReplacementRules.put(Pattern.quote(AzureEnvironment.AZURE.getMicrosoftGraphEndpoint()), PLAYBACK_URI + "/");
296+
// vault endpoint
297+
textReplacementRules.put("https://[a-zA-Z0-9]+?" + AzureEnvironment.AZURE.getKeyVaultDnsSuffix().replace(".", "\\.") + "/", PLAYBACK_URI + "/");
298+
// storage account endpoint
299+
textReplacementRules.put("https://[a-zA-Z0-9]+?" + AzureEnvironment.AZURE.getStorageEndpointSuffix().replace(".", "\\.") + "/", PLAYBACK_URI + "/");
293300
addTextReplacementRules(textReplacementRules);
294301
}
295302
initializeClients(httpPipeline, testProfile);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.resourcemanager;
5+
6+
import com.azure.core.credential.TokenCredential;
7+
import com.azure.core.http.HttpClient;
8+
import com.azure.core.http.HttpPipeline;
9+
import com.azure.core.http.policy.HttpLogOptions;
10+
import com.azure.core.http.policy.HttpPipelinePolicy;
11+
import com.azure.core.http.policy.RetryPolicy;
12+
import com.azure.core.management.Region;
13+
import com.azure.core.management.profile.AzureProfile;
14+
import com.azure.resourcemanager.authorization.models.BuiltInRole;
15+
import com.azure.resourcemanager.compute.fluent.models.DiskEncryptionSetInner;
16+
import com.azure.resourcemanager.compute.models.DiskEncryptionSetIdentityType;
17+
import com.azure.resourcemanager.compute.models.DiskEncryptionSetType;
18+
import com.azure.resourcemanager.compute.models.EncryptionSetIdentity;
19+
import com.azure.resourcemanager.compute.models.KeyForDiskEncryptionSet;
20+
import com.azure.resourcemanager.compute.models.SourceVault;
21+
import com.azure.resourcemanager.keyvault.models.Key;
22+
import com.azure.resourcemanager.keyvault.models.Vault;
23+
import com.azure.resourcemanager.resources.fluentcore.utils.HttpPipelineProvider;
24+
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
25+
import com.azure.resourcemanager.test.ResourceManagerTestBase;
26+
import com.azure.resourcemanager.test.utils.TestDelayProvider;
27+
import com.azure.resourcemanager.test.utils.TestIdentifierProvider;
28+
import com.azure.security.keyvault.keys.models.KeyType;
29+
30+
import java.time.Duration;
31+
import java.time.temporal.ChronoUnit;
32+
import java.util.List;
33+
34+
public class DiskEncryptionTestBase extends ResourceManagerTestBase {
35+
36+
protected AzureResourceManager azureResourceManager;
37+
38+
protected String rgName = "";
39+
protected final Region region = Region.US_EAST;
40+
41+
@Override
42+
protected HttpPipeline buildHttpPipeline(
43+
TokenCredential credential,
44+
AzureProfile profile,
45+
HttpLogOptions httpLogOptions,
46+
List<HttpPipelinePolicy> policies,
47+
HttpClient httpClient) {
48+
return HttpPipelineProvider.buildHttpPipeline(
49+
credential,
50+
profile,
51+
null,
52+
httpLogOptions,
53+
null,
54+
new RetryPolicy("Retry-After", ChronoUnit.SECONDS),
55+
policies,
56+
httpClient);
57+
}
58+
59+
@Override
60+
protected void initializeClients(HttpPipeline httpPipeline, AzureProfile profile) {
61+
ResourceManagerUtils.InternalRuntimeContext.setDelayProvider(new TestDelayProvider(!isPlaybackMode()));
62+
ResourceManagerUtils.InternalRuntimeContext internalContext = new ResourceManagerUtils.InternalRuntimeContext();
63+
internalContext.setIdentifierFunction(name -> new TestIdentifierProvider(testResourceNamer));
64+
azureResourceManager = buildManager(AzureResourceManager.class, httpPipeline, profile);
65+
setInternalContext(internalContext, azureResourceManager);
66+
67+
rgName = generateRandomResourceName("javacsmrg", 15);
68+
}
69+
70+
@Override
71+
protected void cleanUpResources() {
72+
try {
73+
azureResourceManager.resourceGroups().beginDeleteByName(rgName);
74+
} catch (Exception e) {
75+
}
76+
}
77+
78+
protected static final class VaultAndKey {
79+
private final Vault vault;
80+
private final Key key;
81+
82+
private VaultAndKey(Vault vault, Key key) {
83+
this.vault = vault;
84+
this.key = key;
85+
}
86+
}
87+
88+
protected VaultAndKey createVaultAndKey(String name, String clientId) {
89+
// create vault
90+
Vault vault = azureResourceManager.vaults().define(name)
91+
.withRegion(region)
92+
.withNewResourceGroup(rgName)
93+
.withRoleBasedAccessControl()
94+
.withPurgeProtectionEnabled()
95+
.create();
96+
97+
// RBAC for this app
98+
String rbacName = generateRandomUuid();
99+
azureResourceManager.accessManagement().roleAssignments().define(rbacName)
100+
.forServicePrincipal(clientId)
101+
.withBuiltInRole(BuiltInRole.KEY_VAULT_ADMINISTRATOR)
102+
.withResourceScope(vault)
103+
.create();
104+
// wait for propagation time
105+
ResourceManagerUtils.sleep(Duration.ofMinutes(1));
106+
107+
// create key
108+
Key key = vault.keys().define("key1")
109+
.withKeyTypeToCreate(KeyType.RSA)
110+
.withKeySize(4096)
111+
.create();
112+
113+
return new VaultAndKey(vault, key);
114+
}
115+
116+
protected DiskEncryptionSetInner createDiskEncryptionSet(String name, DiskEncryptionSetType type, VaultAndKey vaultAndKey) {
117+
// create disk encryption set
118+
DiskEncryptionSetInner diskEncryptionSet = azureResourceManager.disks().manager().serviceClient()
119+
.getDiskEncryptionSets().createOrUpdate(rgName, name, new DiskEncryptionSetInner()
120+
.withLocation(region.name())
121+
.withEncryptionType(type)
122+
.withIdentity(new EncryptionSetIdentity().withType(DiskEncryptionSetIdentityType.SYSTEM_ASSIGNED))
123+
.withActiveKey(new KeyForDiskEncryptionSet()
124+
.withSourceVault(new SourceVault().withId(vaultAndKey.vault.id()))
125+
.withKeyUrl(vaultAndKey.key.id())));
126+
127+
// RBAC for disk encryption set
128+
String rbacName = generateRandomUuid();
129+
azureResourceManager.accessManagement().roleAssignments().define(rbacName)
130+
.forObjectId(diskEncryptionSet.identity().principalId())
131+
.withBuiltInRole(BuiltInRole.KEY_VAULT_CRYPTO_SERVICE_ENCRYPTION_USER)
132+
.withResourceScope(vaultAndKey.vault)
133+
.create();
134+
135+
return diskEncryptionSet;
136+
}
137+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.resourcemanager;
5+
6+
import com.azure.resourcemanager.compute.fluent.models.DiskEncryptionSetInner;
7+
import com.azure.resourcemanager.compute.models.DiskEncryptionSetType;
8+
import com.azure.resourcemanager.containerservice.models.AgentPoolMode;
9+
import com.azure.resourcemanager.containerservice.models.ContainerServiceVMSizeTypes;
10+
import com.azure.resourcemanager.containerservice.models.KubernetesCluster;
11+
import org.junit.jupiter.api.Assertions;
12+
import org.junit.jupiter.api.Test;
13+
14+
import java.util.Locale;
15+
16+
public class KubernetesEncryptionTests extends DiskEncryptionTestBase {
17+
18+
@Test
19+
public void canCreateClusterWithDiskEncryption() {
20+
final String clientId = this.clientIdFromFile();
21+
22+
// create vault and key
23+
final String vaultName = generateRandomResourceName("kv", 8);
24+
VaultAndKey vaultAndKey = createVaultAndKey(vaultName, clientId);
25+
26+
// create disk encryption set
27+
DiskEncryptionSetInner diskEncryptionSet = createDiskEncryptionSet("des1",
28+
DiskEncryptionSetType.ENCRYPTION_AT_REST_WITH_PLATFORM_AND_CUSTOMER_KEYS, vaultAndKey);
29+
30+
final String aksName = generateRandomResourceName("aks", 15);
31+
final String dnsPrefix = generateRandomResourceName("dns", 10);
32+
final String agentPoolName = generateRandomResourceName("ap0", 10);
33+
34+
// create
35+
KubernetesCluster kubernetesCluster = azureResourceManager
36+
.kubernetesClusters()
37+
.define(aksName)
38+
.withRegion(region)
39+
.withNewResourceGroup(rgName)
40+
.withDefaultVersion()
41+
.withSystemAssignedManagedServiceIdentity()
42+
.disableLocalAccounts()
43+
.withDiskEncryptionSet(diskEncryptionSet.id())
44+
.defineAgentPool(agentPoolName)
45+
.withVirtualMachineSize(ContainerServiceVMSizeTypes.STANDARD_D2_V3)
46+
.withAgentPoolVirtualMachineCount(1)
47+
.withAgentPoolMode(AgentPoolMode.SYSTEM)
48+
.withOSDiskSizeInGB(30)
49+
.attach()
50+
.withDnsPrefix("mp1" + dnsPrefix)
51+
.create();
52+
53+
Assertions.assertEquals(diskEncryptionSet.id().toLowerCase(Locale.ROOT), kubernetesCluster.diskEncryptionSetId().toLowerCase(Locale.ROOT));
54+
}
55+
}

0 commit comments

Comments
 (0)