[
https://issues.apache.org/jira/browse/ARTEMIS-4709?focusedWorklogId=912667&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-912667
]
ASF GitHub Bot logged work on ARTEMIS-4709:
-------------------------------------------
Author: ASF GitHub Bot
Created on: 02/Apr/24 14:29
Start Date: 02/Apr/24 14:29
Worklog Time Spent: 10m
Work Description: gemmellr commented on code in PR #4871:
URL: https://github.com/apache/activemq-artemis/pull/4871#discussion_r1547968121
##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/impl/ConnectionPeriodicExpiryPlugin.java:
##########
@@ -0,0 +1,130 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.activemq.artemis.core.server.plugin.impl;
+
+import java.util.Map;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+import org.apache.activemq.artemis.api.core.ActiveMQDisconnectedException;
+import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor;
+import
org.apache.activemq.artemis.core.remoting.impl.netty.NettyServerConnection;
+import org.apache.activemq.artemis.core.remoting.server.RemotingService;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerBasePlugin;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
+import org.apache.activemq.artemis.utils.RandomUtil;
+
+public class ConnectionPeriodicExpiryPlugin implements
ActiveMQServerBasePlugin {
+
+ private String name;
+ private long periodSeconds;
+ private int accuracyWindowSeconds;
+ private String acceptorMatchRegex;
+
+ private ScheduledExecutorService executor;
+ private RemotingService remotingService;
+ private Pattern matchPattern;
+ private ScheduledFuture<?> task;
+
+ public ConnectionPeriodicExpiryPlugin() {
+ periodSeconds = TimeUnit.MINUTES.toSeconds(15);
+ accuracyWindowSeconds = 30;
+ acceptorMatchRegex = ""; // no match
+ }
+
+ @Override
+ public void registered(ActiveMQServer server) {
+ executor = server.getScheduledPool();
+ remotingService = server.getRemotingService();
+ matchPattern = Pattern.compile(acceptorMatchRegex);
+
+ task = executor.scheduleWithFixedDelay(() -> {
+
+ final long currentTime = System.currentTimeMillis();
+ for (Acceptor acceptor : remotingService.getAcceptors().values()) {
+ if (matchPattern.matcher(acceptor.getName()).matches()) {
+ if (acceptor instanceof NettyAcceptor) {
+ NettyAcceptor nettyAcceptor = (NettyAcceptor) acceptor;
+
+ for (NettyServerConnection nettyServerConnection :
nettyAcceptor.getConnections().values()) {
+ RemotingConnection remotingConnection =
remotingService.getConnection(nettyServerConnection.getID());
+ if (currentTime > remotingConnection.getCreationTime() +
periodSeconds ) {
Review Comment:
Seems like it needs a validity check, connection could have already gone
away by other means while this checking was happening, so perhaps it could NPE
here.
Related...as is, if this task ever throws for any reason (e.g above
potential NPE) the expiry process will then simply stop working as the task
wont be rescheduled.
##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/impl/ConnectionPeriodicExpiryPlugin.java:
##########
@@ -0,0 +1,130 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
Review Comment:
Shouldnt have the \<p\> elements and the URL should be indented. As in the
other files.
##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/impl/ConnectionPeriodicExpiryPlugin.java:
##########
@@ -0,0 +1,130 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.activemq.artemis.core.server.plugin.impl;
+
+import java.util.Map;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+import org.apache.activemq.artemis.api.core.ActiveMQDisconnectedException;
+import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor;
+import
org.apache.activemq.artemis.core.remoting.impl.netty.NettyServerConnection;
+import org.apache.activemq.artemis.core.remoting.server.RemotingService;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerBasePlugin;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
+import org.apache.activemq.artemis.utils.RandomUtil;
+
+public class ConnectionPeriodicExpiryPlugin implements
ActiveMQServerBasePlugin {
+
+ private String name;
+ private long periodSeconds;
+ private int accuracyWindowSeconds;
+ private String acceptorMatchRegex;
+
+ private ScheduledExecutorService executor;
+ private RemotingService remotingService;
+ private Pattern matchPattern;
+ private ScheduledFuture<?> task;
+
+ public ConnectionPeriodicExpiryPlugin() {
+ periodSeconds = TimeUnit.MINUTES.toSeconds(15);
+ accuracyWindowSeconds = 30;
+ acceptorMatchRegex = ""; // no match
+ }
+
+ @Override
+ public void registered(ActiveMQServer server) {
+ executor = server.getScheduledPool();
+ remotingService = server.getRemotingService();
+ matchPattern = Pattern.compile(acceptorMatchRegex);
+
+ task = executor.scheduleWithFixedDelay(() -> {
+
+ final long currentTime = System.currentTimeMillis();
+ for (Acceptor acceptor : remotingService.getAcceptors().values()) {
+ if (matchPattern.matcher(acceptor.getName()).matches()) {
+ if (acceptor instanceof NettyAcceptor) {
+ NettyAcceptor nettyAcceptor = (NettyAcceptor) acceptor;
+
+ for (NettyServerConnection nettyServerConnection :
nettyAcceptor.getConnections().values()) {
+ RemotingConnection remotingConnection =
remotingService.getConnection(nettyServerConnection.getID());
+ if (currentTime > remotingConnection.getCreationTime() +
periodSeconds ) {
+ executor.schedule(() -> {
+
remotingService.removeConnection(remotingConnection.getID());
+ remotingConnection.fail(new
ActiveMQDisconnectedException("terminated by session expiry plugin"));
+ }, RandomUtil.randomMax(accuracyWindowSeconds),
TimeUnit.SECONDS);
+ }
+ }
+ }
+ }
+ }
+ }, accuracyWindowSeconds, accuracyWindowSeconds, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void unregistered(ActiveMQServer server) {
+ task.cancel(true);
+ }
+
+ @Override
+ public void init(Map<String, String> properties) {
+ name = properties.getOrDefault("name", name);
+ periodSeconds = Long.parseLong(properties.getOrDefault("periodSeconds",
Long.toString(periodSeconds)));
+ accuracyWindowSeconds =
Integer.parseInt(properties.getOrDefault("accuracyWindowSeconds",
Long.toString(accuracyWindowSeconds)));
+ if (accuracyWindowSeconds <= 0) {
+ throw new IllegalArgumentException("accuracyWindowSeconds must be >
0");
+ }
+ acceptorMatchRegex = properties.getOrDefault("acceptorMatchRegex",
acceptorMatchRegex);
Review Comment:
Should it even be allowed to configure it with an empty regex, as it seems
this would?
##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/impl/ConnectionPeriodicExpiryPlugin.java:
##########
@@ -0,0 +1,130 @@
+/**
Review Comment:
Shouldnt be a javadoc
##########
docs/user-manual/broker-plugins.adoc:
##########
@@ -178,3 +178,30 @@ In the example below `ROLE_PROPERTY` is set to
`permissions` when that property
</broker-plugin>
</broker-plugins>
----
+
+== Using the ConnectionPeriodicExpiryPlugin
+
+The `ConnectionPeriodicExpiryPlugin` will implement a global expiry (and
disconnect) for connections that live longer than `periodSeconds` on a matching
acceptor basis.
+
+This plugin can be useful when credential rotation or credential validation
must be enforced at regular intervals as authentication will be enforced on
reconnect.
+
+The plugin requires the configuration of the `acceptorMatchRegex` to determine
the acceptors to monitor. It is typical to separate client acceptors and
federation or cluster acceptors such that only client connections will be
subject to periodic expiry. The `acceptorMatchRegex` must be configured to
match the name of the acceptor(s) whose connections will be subject to periodic
expiry.
+
+|===
+| Property | Property Description | Default Value
+
+|`acceptorMatchRegex`|the regular expression used to match against the names
of acceptors to monitor | ""
+|`periodSeconds`|the max duration or period, in seconds, that a connection can
last | 15 minutes (as seconds)
Review Comment:
the default would be more obvious if offered in the way it is to actually be
used, e.g: "900 (i.e 15 minutes)"
Issue Time Tracking
-------------------
Worklog Id: (was: 912667)
Time Spent: 20m (was: 10m)
> Add a plugin to provide periodic expiry of connections on a per acceptor basis
> ------------------------------------------------------------------------------
>
> Key: ARTEMIS-4709
> URL: https://issues.apache.org/jira/browse/ARTEMIS-4709
> Project: ActiveMQ Artemis
> Issue Type: New Feature
> Components: Broker
> Affects Versions: 2.33.0
> Reporter: Gary Tully
> Assignee: Gary Tully
> Priority: Major
> Fix For: 2.34.0
>
> Time Spent: 20m
> Remaining Estimate: 0h
>
> When credential rotation needs to be enforced, active connections need to be
> terminated on some timeline to ensure credentials are reevaluated. There are
> management apis that can be used but these require some intervention.
> In addition to enforce some SLA around duration of connections, having an
> easy way to limit connections to a given maximum period can be helpful.
> A plugin that will be applied on an per acceptor basis, that can be used to
> disconnect connections that have lived for some period can provide a nice
> building block for these use cases.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)