blob: 3c0103f6effb563face42486dccbc835183eb6b8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.protocol.protobuf.v1.acceptance;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.Socket;
import java.util.Properties;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.ConfigurationProperties;
import org.apache.geode.distributed.Locator;
import org.apache.geode.examples.SimpleSecurityManager;
import org.apache.geode.internal.protocol.protobuf.v1.ClientProtocol;
import org.apache.geode.internal.protocol.protobuf.v1.ConnectionAPI;
import org.apache.geode.internal.protocol.protobuf.v1.MessageUtil;
import org.apache.geode.internal.protocol.protobuf.v1.ProtobufRequestUtilities;
import org.apache.geode.internal.protocol.protobuf.v1.serializer.ProtobufProtocolSerializer;
import org.apache.geode.internal.protocol.protobuf.v1.state.exception.ConnectionStateException;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.rules.DistributedRestoreSystemProperties;
import org.apache.geode.test.junit.categories.ClientServerTest;
/**
* Test sending ProtoBuf messages to the locator, with a security manager configured on the locator
*/
@Category(ClientServerTest.class)
public class LocatorConnectionAuthenticationDUnitTest {
@Rule
public final DistributedRestoreSystemProperties restoreDistributedSystemProperties =
new DistributedRestoreSystemProperties();
private int locatorPort;
// only used for cleanup on VM 1.
private static Locator locator;
private VM locatorVM;
private Cache cache;
@Before
public void setup() throws IOException {
// Start a new locator with authorization
locatorVM = VM.getVM(0);
locatorPort = locatorVM.invoke(() -> {
System.setProperty("geode.feature-protobuf-protocol", "true");
Properties props = new Properties();
props.setProperty(ConfigurationProperties.SECURITY_MANAGER,
SimpleSecurityManager.class.getName());
locator = Locator.startLocatorAndDS(0, null, props);
return locator.getPort();
});
startCacheWithCacheServer(locatorPort);
}
@After
public void tearDown() {
try {
locatorVM.invoke(() -> locator.stop());
locator = null;
} finally {
cache.close();
cache = null;
}
}
private void startCacheWithCacheServer(int locatorPort) throws IOException {
System.setProperty("geode.feature-protobuf-protocol", "true");
Properties props = new Properties();
props.setProperty(ConfigurationProperties.LOCATORS, "localhost[" + locatorPort + "]");
props.setProperty("security-username", "cluster");
props.setProperty("security-password", "cluster");
props.setProperty(ConfigurationProperties.USE_CLUSTER_CONFIGURATION, "true");
cache = new CacheFactory(props).create();
final CacheServer cacheServer = cache.addCacheServer();
cacheServer.setPort(0);
cacheServer.start();
}
private Socket createSocket() throws IOException {
Socket socket = new Socket(VM.getHostName(), locatorPort);
MessageUtil.sendHandshake(socket);
MessageUtil.verifyHandshakeSuccess(socket);
return socket;
}
/**
* Test that if the locator has a security manager, an authorized client is allowed to get an
* available server
*/
@Test
public void authorizedClientCanGetServersIfSecurityIsEnabled() throws Throwable {
ClientProtocol.Message authorization = ClientProtocol.Message.newBuilder()
.setHandshakeRequest(ConnectionAPI.HandshakeRequest.newBuilder()
.putCredentials("security-username", "cluster").putCredentials("security-password",
"cluster"))
.build();
ClientProtocol.Message getServerRequestMessage = ClientProtocol.Message.newBuilder()
.setGetServerRequest(ProtobufRequestUtilities.createGetServerRequest()).build();
ProtobufProtocolSerializer protobufProtocolSerializer = new ProtobufProtocolSerializer();
try (Socket socket = createSocket()) {
protobufProtocolSerializer.serialize(authorization, socket.getOutputStream());
ClientProtocol.Message authorizationResponse =
protobufProtocolSerializer.deserialize(socket.getInputStream());
assertTrue(authorizationResponse.getHandshakeResponse().getAuthenticated());
protobufProtocolSerializer.serialize(getServerRequestMessage, socket.getOutputStream());
ClientProtocol.Message GetServerResponseMessage =
protobufProtocolSerializer.deserialize(socket.getInputStream());
assertTrue("Got response: " + GetServerResponseMessage,
GetServerResponseMessage.getGetServerResponse().hasServer());
}
}
/**
* Test that if the locator has a security manager, an unauthorized client is not allowed to do
* anything.
*/
@Test
public void unauthorizedClientCannotGetServersIfSecurityIsEnabled() throws Throwable {
IgnoredException.addIgnoredException(ConnectionStateException.class);
ClientProtocol.Message getServerRequestMessage = ClientProtocol.Message.newBuilder()
.setGetServerRequest(ProtobufRequestUtilities.createGetServerRequest()).build();
ProtobufProtocolSerializer protobufProtocolSerializer = new ProtobufProtocolSerializer();
try (Socket socket = createSocket()) {
protobufProtocolSerializer.serialize(getServerRequestMessage, socket.getOutputStream());
ClientProtocol.Message getServerResponseMessage =
protobufProtocolSerializer.deserialize(socket.getInputStream());
assertNotNull("Got response: " + getServerResponseMessage,
getServerRequestMessage.getErrorResponse());
}
}
}