Skip to content

Commit 90d2fa4

Browse files
committed
Check access to Kubernetes CNI user data
1 parent d02adcd commit 90d2fa4

3 files changed

Lines changed: 76 additions & 0 deletions

File tree

‎plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,19 @@ public boolean isCommandSupported(KubernetesCluster cluster, String cmdName) {
10191019
}
10201020
}
10211021

1022+
protected void validateCniConfiguration(Long cniConfigId) {
1023+
if (cniConfigId == null) {
1024+
return;
1025+
}
1026+
UserDataVO userData = userDataDao.findById(cniConfigId);
1027+
if (userData == null) {
1028+
throw new InvalidParameterValueException("Unable to find user data with the specified ID.");
1029+
}
1030+
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, false, userData);
1031+
}
1032+
10221033
private void validateManagedKubernetesClusterCreateParameters(final CreateKubernetesClusterCmd cmd) throws CloudRuntimeException {
1034+
validateCniConfiguration(cmd.getCniConfigId());
10231035
ApiServiceConfiguration.validateEndpointUrl();
10241036
final String name = cmd.getName();
10251037
final Long zoneId = cmd.getZoneId();

‎plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ public class CreateKubernetesClusterCmd extends BaseAsyncCreateCmd {
197197
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, description = "the hypervisor on which the CKS cluster is to be deployed. This is required if the zone in which the CKS cluster is being deployed has clusters with different hypervisor types.", since = "4.21.0")
198198
private String hypervisor;
199199

200+
@ACL
200201
@Parameter(name = ApiConstants.CNI_CONFIG_ID, type = CommandType.UUID, entityType = UserDataResponse.class, description = "the ID of the Userdata", since = "4.21.0")
201202
private Long cniConfigId;
202203

‎plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImplTest.java‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,15 @@
4242
import com.cloud.user.Account;
4343
import com.cloud.user.AccountManager;
4444
import com.cloud.user.User;
45+
import com.cloud.user.UserDataVO;
46+
import com.cloud.user.dao.UserDataDao;
4547
import com.cloud.utils.Pair;
4648
import com.cloud.utils.net.NetUtils;
4749
import com.cloud.vm.VMInstanceVO;
4850
import com.cloud.vm.dao.VMInstanceDao;
4951
import org.apache.cloudstack.api.BaseCmd;
5052
import org.apache.cloudstack.api.command.user.kubernetes.cluster.AddVirtualMachinesToKubernetesClusterCmd;
53+
import org.apache.cloudstack.api.command.user.kubernetes.cluster.CreateKubernetesClusterCmd;
5154
import org.apache.cloudstack.api.command.user.kubernetes.cluster.RemoveVirtualMachinesFromKubernetesClusterCmd;
5255
import org.apache.cloudstack.context.CallContext;
5356
import org.apache.cloudstack.framework.config.ConfigKey;
@@ -103,10 +106,70 @@ public class KubernetesClusterManagerImplTest {
103106
@Mock
104107
private ServiceOfferingDao serviceOfferingDao;
105108

109+
@Mock
110+
private UserDataDao userDataDao;
111+
106112
@Spy
107113
@InjectMocks
108114
KubernetesClusterManagerImpl kubernetesClusterManager;
109115

116+
@Test
117+
public void testValidateCniConfigurationNotSpecified() {
118+
kubernetesClusterManager.validateCniConfiguration(null);
119+
120+
Mockito.verifyNoInteractions(userDataDao);
121+
}
122+
123+
@Test
124+
public void testValidateCniConfigurationAccessible() {
125+
UserDataVO userData = new UserDataVO();
126+
userData.setAccountId(CallContext.current().getCallingAccount().getId());
127+
Mockito.when(userDataDao.findById(1L)).thenReturn(userData);
128+
129+
kubernetesClusterManager.validateCniConfiguration(1L);
130+
131+
Mockito.verify(accountManager).checkAccess(CallContext.current().getCallingAccount(), null, false, userData);
132+
}
133+
134+
@Test
135+
public void testCreateManagedClusterRejectsInaccessibleCniConfiguration() {
136+
CreateKubernetesClusterCmd cmd = Mockito.mock(CreateKubernetesClusterCmd.class);
137+
Mockito.when(cmd.getCniConfigId()).thenReturn(1L);
138+
UserDataVO userData = new UserDataVO();
139+
userData.setAccountId(CallContext.current().getCallingAccount().getId() + 1);
140+
Mockito.when(userDataDao.findById(1L)).thenReturn(userData);
141+
PermissionDeniedException denied = new PermissionDeniedException("UserData access denied");
142+
Mockito.doThrow(denied).when(accountManager).checkAccess(
143+
CallContext.current().getCallingAccount(), null, false, userData);
144+
145+
try {
146+
kubernetesClusterManager.createManagedKubernetesCluster(cmd);
147+
Assert.fail("Expected UserData access denial");
148+
} catch (PermissionDeniedException expected) {
149+
Assert.assertSame(denied, expected);
150+
}
151+
152+
Mockito.verifyNoInteractions(kubernetesClusterDao);
153+
Mockito.verify(cmd, Mockito.never()).getZoneId();
154+
Mockito.verify(cmd, Mockito.never()).getCniConfigDetails();
155+
}
156+
157+
@Test
158+
public void testCreateManagedClusterRejectsMissingCniConfiguration() {
159+
CreateKubernetesClusterCmd cmd = Mockito.mock(CreateKubernetesClusterCmd.class);
160+
Mockito.when(cmd.getCniConfigId()).thenReturn(1L);
161+
162+
try {
163+
kubernetesClusterManager.createManagedKubernetesCluster(cmd);
164+
Assert.fail("Expected missing UserData rejection");
165+
} catch (InvalidParameterValueException expected) {
166+
Assert.assertEquals("Unable to find user data with the specified ID.", expected.getMessage());
167+
}
168+
169+
Mockito.verifyNoInteractions(kubernetesClusterDao);
170+
Mockito.verify(cmd, Mockito.never()).getZoneId();
171+
}
172+
110173
@Test
111174
public void testValidateVpcTierAllocated() {
112175
Network network = Mockito.mock(Network.class);

0 commit comments

Comments
 (0)