Skip to content

Commit 6ecb8ec

Browse files
committed
server: scope the Impl2 IPv6 security group member rule to the exact host
1 parent 8c6df72 commit 6ecb8ec

2 files changed

Lines changed: 83 additions & 1 deletion

File tree

‎server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl2.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ protected Map<PortAndProto, Set<String>> generateRulesForVM(Long userVmId, Secur
250250
String cidr = ngmapVO.getGuestIpAddress() + "/32";
251251
cidrs.add(cidr);
252252
if (ngmapVO.getGuestIpv6Address() != null) {
253-
cidrs.add(ngmapVO.getGuestIpv6Address() + "/64");
253+
cidrs.add(ngmapVO.getGuestIpv6Address() + "/128");
254254
}
255255
}
256256
} else if (rule.getAllowedSourceIpCidr() != null) {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.network.security;
18+
19+
import static org.mockito.Mockito.when;
20+
21+
import java.util.Collections;
22+
import java.util.Map;
23+
import java.util.Set;
24+
25+
import org.junit.Assert;
26+
import org.junit.Test;
27+
import org.junit.runner.RunWith;
28+
import org.mockito.InjectMocks;
29+
import org.mockito.Mock;
30+
import org.mockito.Mockito;
31+
import org.mockito.junit.MockitoJUnitRunner;
32+
33+
import com.cloud.network.security.SecurityGroupManagerImpl.PortAndProto;
34+
import com.cloud.network.security.SecurityRule.SecurityRuleType;
35+
import com.cloud.network.security.dao.SecurityGroupRuleDao;
36+
import com.cloud.network.security.dao.SecurityGroupVMMapDao;
37+
import com.cloud.vm.VirtualMachine.State;
38+
39+
@RunWith(MockitoJUnitRunner.Silent.class)
40+
public class SecurityGroupManagerImpl2Ipv6RuleTest {
41+
42+
@Mock
43+
SecurityGroupRuleDao _securityGroupRuleDao;
44+
@Mock
45+
SecurityGroupVMMapDao _securityGroupVMMapDao;
46+
47+
@InjectMocks
48+
SecurityGroupManagerImpl2 manager = new SecurityGroupManagerImpl2();
49+
50+
@Test
51+
public void securityGroupMemberRuleUsesExactIpv6HostCidr() {
52+
Long vmId = 1L;
53+
SecurityRuleType type = SecurityRuleType.IngressRule;
54+
55+
// The VM belongs to security group 10, which has one rule referencing another security group (20).
56+
SecurityGroupVMMapVO groupMap = Mockito.mock(SecurityGroupVMMapVO.class);
57+
when(groupMap.getSecurityGroupId()).thenReturn(10L);
58+
when(_securityGroupVMMapDao.listByInstanceId(vmId)).thenReturn(Collections.singletonList(groupMap));
59+
60+
SecurityGroupRuleVO rule = Mockito.mock(SecurityGroupRuleVO.class);
61+
when(rule.getProtocol()).thenReturn("tcp");
62+
when(rule.getStartPort()).thenReturn(80);
63+
when(rule.getEndPort()).thenReturn(80);
64+
when(rule.getAllowedNetworkId()).thenReturn(20L);
65+
when(_securityGroupRuleDao.listBySecurityGroupId(10L, type)).thenReturn(Collections.singletonList(rule));
66+
67+
// Unlike the superclass, Impl2 reads the member addresses straight from the VO join, not the nics table.
68+
SecurityGroupVMMapVO memberMap = Mockito.mock(SecurityGroupVMMapVO.class);
69+
when(memberMap.getGuestIpAddress()).thenReturn("10.1.1.5");
70+
when(memberMap.getGuestIpv6Address()).thenReturn("2001:db8::5");
71+
when(_securityGroupVMMapDao.listBySecurityGroup(20L, State.Running)).thenReturn(Collections.singletonList(memberMap));
72+
73+
Map<PortAndProto, Set<String>> allowed = manager.generateRulesForVM(vmId, type);
74+
75+
Assert.assertEquals(1, allowed.size());
76+
Set<String> cidrs = allowed.values().iterator().next();
77+
// The member must be authorized as an exact host, matching the IPv4 /32 behaviour.
78+
Assert.assertTrue("IPv4 member should be pinned to /32", cidrs.contains("10.1.1.5/32"));
79+
Assert.assertTrue("IPv6 member should be pinned to the exact /128 host", cidrs.contains("2001:db8::5/128"));
80+
Assert.assertFalse("IPv6 member must not open the whole /64 subnet", cidrs.contains("2001:db8::5/64"));
81+
}
82+
}

0 commit comments

Comments
 (0)