Skip to content

Commit bd16446

Browse files
authored
fix: ensure the session we are closing is not the current session (#118)
1 parent 33538c6 commit bd16446

File tree

6 files changed

+491
-24
lines changed

6 files changed

+491
-24
lines changed

integration/pom.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,39 @@
391391
</execution>
392392
</executions>
393393
</plugin>
394+
<plugin>
395+
<groupId>org.codehaus.mojo</groupId>
396+
<artifactId>build-helper-maven-plugin</artifactId>
397+
<version>3.0.0</version>
398+
<executions>
399+
<execution>
400+
<id>add-integration-test-source</id>
401+
<phase>generate-test-sources</phase>
402+
<goals>
403+
<goal>add-test-source</goal>
404+
</goals>
405+
<configuration>
406+
<sources>
407+
<source>src/integrationtests/java</source>
408+
</sources>
409+
</configuration>
410+
</execution>
411+
<execution>
412+
<id>add-integration-test-resource</id>
413+
<phase>generate-test-resources</phase>
414+
<goals>
415+
<goal>add-test-resource</goal>
416+
</goals>
417+
<configuration>
418+
<resources>
419+
<resource>
420+
<directory>src/integrationtests/resources</directory>
421+
</resource>
422+
</resources>
423+
</configuration>
424+
</execution>
425+
</executions>
426+
</plugin>
394427
</plugins>
395428
</build>
396429
<properties>
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package com.aws.greengrass.integrationtests;
7+
8+
import com.aws.greengrass.clientdevices.auth.api.ClientDevicesAuthServiceApi;
9+
import com.aws.greengrass.clientdevices.auth.certificate.CertificateHelper;
10+
import com.aws.greengrass.clientdevices.auth.iot.Certificate;
11+
import com.aws.greengrass.clientdevices.auth.iot.IotAuthClient;
12+
import com.aws.greengrass.clientdevices.auth.iot.Thing;
13+
import com.aws.greengrass.dependency.State;
14+
import com.aws.greengrass.integrationtests.helpers.CertificateTestHelpersMoquette;
15+
import com.aws.greengrass.lifecyclemanager.GlobalStateChangeListener;
16+
import com.aws.greengrass.lifecyclemanager.GreengrassService;
17+
import com.aws.greengrass.lifecyclemanager.Kernel;
18+
import com.aws.greengrass.mqtt.moquette.ClientDeviceAuthorizer;
19+
import com.aws.greengrass.mqtt.moquette.MQTTService;
20+
import com.aws.greengrass.mqttclient.spool.SpoolerStoreException;
21+
import com.aws.greengrass.testcommons.testutilities.GGExtension;
22+
import io.moquette.broker.subscriptions.Topic;
23+
import io.moquette.interception.messages.InterceptDisconnectMessage;
24+
import org.junit.jupiter.api.AfterEach;
25+
import org.junit.jupiter.api.BeforeEach;
26+
import org.junit.jupiter.api.Test;
27+
import org.junit.jupiter.api.extension.ExtendWith;
28+
import org.junit.jupiter.api.extension.ExtensionContext;
29+
import org.junit.jupiter.api.io.TempDir;
30+
import org.mockito.Mock;
31+
import org.mockito.junit.jupiter.MockitoExtension;
32+
33+
import java.nio.file.NoSuchFileException;
34+
import java.nio.charset.StandardCharsets;
35+
import java.nio.file.Path;
36+
import java.security.KeyStoreException;
37+
import java.security.UnrecoverableKeyException;
38+
import java.security.cert.X509Certificate;
39+
import java.util.List;
40+
import java.util.Optional;
41+
import java.util.concurrent.CountDownLatch;
42+
import java.util.concurrent.TimeUnit;
43+
44+
import static com.aws.greengrass.testcommons.testutilities.ExceptionLogProtector.ignoreExceptionOfType;
45+
import static org.junit.jupiter.api.Assertions.assertTrue;
46+
import static org.mockito.Mockito.when;
47+
48+
@ExtendWith({GGExtension.class, MockitoExtension.class})
49+
public class ClientDeviceAuthorizerIntegrationTest {
50+
private Kernel kernel;
51+
private static final String DEFAULT_CLIENT = "myThing";
52+
private static final String DEFAULT_TOPIC = "topic";
53+
private static final byte[] DEFAULT_PASSWORD = "".getBytes(StandardCharsets.UTF_8);
54+
private static final long TEST_TIME_OUT_SEC = 30L;
55+
@TempDir
56+
Path rootDir;
57+
private final Optional<String> certId = Optional.of("certId");
58+
private String clientPem;
59+
@Mock
60+
IotAuthClient iotAuthClient;
61+
62+
@BeforeEach
63+
void setup(ExtensionContext context) throws Exception {
64+
ignoreExceptionOfType(context, SpoolerStoreException.class);
65+
ignoreExceptionOfType(context, NoSuchFileException.class); // Loading CA keystore
66+
ignoreExceptionOfType(context, NullPointerException.class); // Uploading Core Device CA
67+
ignoreExceptionOfType(context, KeyStoreException.class);
68+
ignoreExceptionOfType(context, UnrecoverableKeyException.class);
69+
70+
// Set this property for kernel to scan its own classpath to find plugins
71+
System.setProperty("aws.greengrass.scanSelfClasspath", "true");
72+
startNucleusWithConfig();
73+
74+
List<X509Certificate> clientCertificates = CertificateTestHelpersMoquette.createClientCertificates(1);
75+
this.clientPem = CertificateHelper.toPem(clientCertificates.get(0));
76+
}
77+
78+
@AfterEach
79+
void cleanup() {
80+
kernel.shutdown();
81+
}
82+
83+
private void startNucleusWithConfig() throws InterruptedException {
84+
kernel = new Kernel();
85+
kernel.getContext().put(IotAuthClient.class, iotAuthClient);
86+
87+
CountDownLatch serviceRunning = new CountDownLatch(1);
88+
kernel.parseArgs("-r", rootDir.toAbsolutePath().toString(), "-i",
89+
getClass().getResource("config.yaml").toString());
90+
GlobalStateChangeListener listener = (GreengrassService service, State was, State newState) -> {
91+
if (service.getName().equals(MQTTService.SERVICE_NAME) && service.getState().equals(State.RUNNING)) {
92+
serviceRunning.countDown();
93+
}
94+
};
95+
kernel.getContext().addGlobalStateChangeListener(listener);
96+
kernel.launch();
97+
assertTrue(serviceRunning.await(TEST_TIME_OUT_SEC, TimeUnit.SECONDS));
98+
kernel.getContext().removeGlobalStateChangeListener(listener);
99+
}
100+
101+
@Test
102+
void GIVEN_duplicate_client_ids_WHEN_check_valid_THEN_can_read_returns_true() {
103+
ClientDevicesAuthServiceApi clientDevicesAuthServiceApi = kernel.getContext().get(ClientDevicesAuthServiceApi.class);
104+
105+
ClientDeviceAuthorizer clientDeviceAuthorizer = new ClientDeviceAuthorizer(clientDevicesAuthServiceApi);
106+
107+
Topic topic = new Topic(DEFAULT_TOPIC);
108+
Thing thing = new Thing(DEFAULT_CLIENT);
109+
Certificate cert = new Certificate(this.certId.get());
110+
when(iotAuthClient.getActiveCertificateId(this.clientPem)).thenReturn(this.certId);
111+
when(iotAuthClient.isThingAttachedToCertificate(thing, cert)).thenReturn(true);
112+
113+
assertTrue(clientDeviceAuthorizer.checkValid(DEFAULT_CLIENT, this.clientPem, DEFAULT_PASSWORD));
114+
assertTrue(clientDeviceAuthorizer.checkValid(DEFAULT_CLIENT, this.clientPem, DEFAULT_PASSWORD));
115+
assertTrue(clientDeviceAuthorizer.canRead(topic, this.clientPem, DEFAULT_CLIENT));
116+
}
117+
118+
@Test
119+
void GIVEN_authorized_client_WHEN_session_closes_THEN_can_read_returns_true() {
120+
ClientDevicesAuthServiceApi clientDevicesAuthServiceApi = kernel.getContext().get(ClientDevicesAuthServiceApi.class);
121+
122+
ClientDeviceAuthorizer clientDeviceAuthorizer = new ClientDeviceAuthorizer(clientDevicesAuthServiceApi);
123+
124+
ClientDeviceAuthorizer.ConnectionTerminationListener connectionTerminationListener =
125+
clientDeviceAuthorizer.new ConnectionTerminationListener();
126+
127+
Topic topic = new Topic(DEFAULT_TOPIC);
128+
Thing thing = new Thing(DEFAULT_CLIENT);
129+
Certificate cert = new Certificate(this.certId.get());
130+
when(iotAuthClient.getActiveCertificateId(this.clientPem)).thenReturn(this.certId);
131+
when(iotAuthClient.isThingAttachedToCertificate(thing, cert)).thenReturn(true);
132+
133+
assertTrue(clientDeviceAuthorizer.checkValid(DEFAULT_CLIENT, this.clientPem, DEFAULT_PASSWORD));
134+
135+
InterceptDisconnectMessage msg = new InterceptDisconnectMessage(DEFAULT_CLIENT, this.clientPem);
136+
connectionTerminationListener.onDisconnect(msg);
137+
138+
assertTrue(clientDeviceAuthorizer.canRead(topic, this.clientPem, DEFAULT_CLIENT));
139+
assertTrue(clientDeviceAuthorizer.checkValid(DEFAULT_CLIENT, this.clientPem, DEFAULT_PASSWORD));
140+
}
141+
}
142+

0 commit comments

Comments
 (0)