Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
nizhikov committed Dec 22, 2024
1 parent 245e4d2 commit f2ab882
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.io.Closeable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.configuration.ClientConnectorConfiguration;
Expand All @@ -41,12 +42,14 @@
import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
import org.apache.ignite.internal.processors.platform.client.ClientStatus;
import org.apache.ignite.internal.processors.security.OperationSecurityContext;
import org.apache.ignite.internal.processors.security.SecurityContext;
import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.nio.GridNioFuture;
import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter;
import org.apache.ignite.internal.util.nio.GridNioSession;
import org.apache.ignite.internal.util.nio.GridNioSessionMetaKey;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.plugin.security.SecurityPermission;
import org.jetbrains.annotations.Nullable;

import static org.apache.ignite.internal.processors.odbc.ClientListenerMetrics.clientTypeLabel;
Expand Down Expand Up @@ -100,6 +103,17 @@ public class ClientListenerNioListener extends GridNioServerListenerAdapter<Clie
/** Metrics. */
private final ClientListenerMetrics metrics;

/**
* If return {@code true} for connection type then proptocol connection allowed by administrator.
* Predicate checks distributed property value.
*
* @see ClientListenerProcessor#registerDistributedProperties
* @see ClientListenerNioListener#ODBC_CLIENT
* @see ClientListenerNioListener#JDBC_CLIENT
* @see ClientListenerNioListener#THIN_CLIENT
*/
private final Predicate<Byte> connAllowed;

/**
* Constructor.
*
Expand All @@ -112,7 +126,8 @@ public ClientListenerNioListener(
GridKernalContext ctx,
GridSpinBusyLock busyLock,
ClientConnectorConfiguration cliConnCfg,
ClientListenerMetrics metrics
ClientListenerMetrics metrics,
Predicate<Byte> connAllowed
) {
assert cliConnCfg != null;

Expand All @@ -123,10 +138,12 @@ public ClientListenerNioListener(
maxCursors = cliConnCfg.getMaxOpenCursorsPerConnection();
log = ctx.log(getClass());

thinCfg = cliConnCfg.getThinClientConfiguration() == null ? new ThinClientConfiguration()
thinCfg = cliConnCfg.getThinClientConfiguration() == null
? new ThinClientConfiguration()
: new ThinClientConfiguration(cliConnCfg.getThinClientConfiguration());

this.metrics = metrics;
this.connAllowed = connAllowed;
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -372,22 +389,10 @@ private void onHandshake(GridNioSession ses, ClientMessage msg) {
try {
connCtx = prepareContext(clientType, ses);

ensureClientPermissions(clientType);

if (connCtx.isVersionSupported(ver)) {
connCtx.initializeFromHandshake(ses, ver, reader);

if (nodeInRecoveryMode()) {
if (!connCtx.isManagementClient())
throw new ClientConnectionNodeRecoveryException("Node in recovery mode.");
}
else if (connDisabled) {
connCtx.clientType()
this.ctx.distributedMetastorage().reg
if (connCtx.isManagementClient()) {
// check security.
}
}
ensureClientPermissions(clientType, connCtx);

ses.addMeta(CONN_CTX_META_KEY, connCtx);
}
Expand Down Expand Up @@ -509,9 +514,10 @@ private boolean nodeInRecoveryMode() {
* Ensures if the given type of client is enabled by config.
*
* @param clientType Client type.
* @param connCtx
* @throws IgniteCheckedException If failed.
*/
private void ensureClientPermissions(byte clientType) throws IgniteCheckedException {
private void ensureClientPermissions(byte clientType, ClientListenerConnectionContext connCtx) throws IgniteCheckedException {
switch (clientType) {
case ODBC_CLIENT: {
if (!cliConnCfg.isOdbcEnabled())
Expand Down Expand Up @@ -539,5 +545,25 @@ private void ensureClientPermissions(byte clientType) throws IgniteCheckedExcept
default:
throw new IgniteCheckedException("Unknown client type: " + clientType);
}

boolean controlShClient = clientType == THIN_CLIENT && connCtx.isManagementClient();

if (nodeInRecoveryMode()) {
if (!controlShClient)
throw new ClientConnectionNodeRecoveryException("Node in recovery mode.");
}

if (!connAllowed.test(clientType)) {
// Allow to connect by the control.sh even if connection disabled to be able to invoke commands.
if (!controlShClient)
throw new IgniteCheckedException("Connection disabled by administrator");

// TODO: checkme
if (connCtx.securityContext() != null) {
try (OperationSecurityContext ignored = ctx.security().withContext(connCtx.securityContext())) {
ctx.security().authorize(SecurityPermission.CONNECT_AS_MAMAGEMENT_CLIENT);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.cache.configuration.Factory;
import javax.management.JMException;
import javax.management.ObjectName;
Expand All @@ -39,9 +41,13 @@
import org.apache.ignite.configuration.OdbcConfiguration;
import org.apache.ignite.configuration.SqlConnectorConfiguration;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.cluster.DistributedConfigurationUtils;
import org.apache.ignite.internal.managers.systemview.walker.ClientConnectionAttributeViewWalker;
import org.apache.ignite.internal.managers.systemview.walker.ClientConnectionViewWalker;
import org.apache.ignite.internal.processors.GridProcessorAdapter;
import org.apache.ignite.internal.processors.configuration.distributed.DistributedBooleanProperty;
import org.apache.ignite.internal.processors.configuration.distributed.DistributedConfigurationLifecycleListener;
import org.apache.ignite.internal.processors.configuration.distributed.DistributedPropertyDispatcher;
import org.apache.ignite.internal.processors.configuration.distributed.DistributedThinClientConfiguration;
import org.apache.ignite.internal.processors.metric.MetricRegistryImpl;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext;
Expand Down Expand Up @@ -71,6 +77,9 @@
import static org.apache.ignite.internal.processors.odbc.ClientListenerMetrics.clientTypeLabel;
import static org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.CLI_TYPES;
import static org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.CONN_CTX_META_KEY;
import static org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.JDBC_CLIENT;
import static org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.ODBC_CLIENT;
import static org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.THIN_CLIENT;

/**
* Client connector processor.
Expand Down Expand Up @@ -177,12 +186,21 @@ public ClientListenerProcessor(GridKernalContext ctx) {
? this::onOutboundMessageOffered
: null;

Map<Byte, DistributedBooleanProperty> allowConnMap = registerDistributedProperties();

Predicate<Byte> connAllowed = type -> {
assert type != null : "Connection type is null";
assert allowConnMap.containsKey(type) : "Unknown connection type: " + type;

return allowConnMap.get(type).get() != Boolean.FALSE;
};

for (int port = cliConnCfg.getPort(); port <= portTo && port <= 65535; port++) {
try {
srv = GridNioServer.<ClientMessage>builder()
.address(hostAddr)
.port(port)
.listener(new ClientListenerNioListener(ctx, busyLock, cliConnCfg, metrics))
.listener(new ClientListenerNioListener(ctx, busyLock, cliConnCfg, metrics, connAllowed))
.logger(log)
.selectorCount(selectorCnt)
.igniteInstanceName(ctx.igniteInstanceName())
Expand Down Expand Up @@ -248,6 +266,31 @@ public ClientListenerProcessor(GridKernalContext ctx) {
}
}

private Map<Byte, DistributedBooleanProperty> registerDistributedProperties() {
Map<Byte, DistributedBooleanProperty> allowConnMap = new HashMap<>();

Function<String, DistributedBooleanProperty> prop = type -> DistributedBooleanProperty.detachedBooleanProperty(
"allowNew" + type + "Connections",
"If true then new " + type.toUpperCase() + " connections allowed. Default is true."
);

allowConnMap.put(ODBC_CLIENT, prop.apply("Odbc"));
allowConnMap.put(JDBC_CLIENT, prop.apply("Jdbc"));
allowConnMap.put(THIN_CLIENT, prop.apply("Thin"));

ctx.internalSubscriptionProcessor().registerDistributedConfigurationListener(new DistributedConfigurationLifecycleListener() {
@Override public void onReadyToRegister(DistributedPropertyDispatcher dispatcher) {
allowConnMap.values().forEach(dispatcher::registerProperty);
}

@Override public void onReadyToWrite() {
allowConnMap.values().forEach(prop -> DistributedConfigurationUtils.setDefaultValue(prop, true, log));
}
});

return allowConnMap;
}

/** */
private Iterable<ClientConnectionAttributeView> connectionAttributeViewSupplier(Map<String, Object> filter) {
Long connId = (Long)filter.get(ClientConnectionAttributeViewWalker.CONNECTION_ID_FILTER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public OdbcConnectionContext(GridKernalContext ctx, GridNioSession ses, GridSpin
}
}

authenticate(ses, user, passwd, false);
authenticate(ses, user, passwd);

ClientListenerResponseSender snd = new ClientListenerResponseSender() {
@Override public void send(ClientListenerResponse resp) {
Expand Down

0 comments on commit f2ab882

Please sign in to comment.