From 4922f8b3301bc74e78c0d1228738c8b63646f194 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 10 Mar 2023 13:44:05 +0400 Subject: [PATCH 001/266] reorg default ticket registry to support pub/sub models --- .../TicketRegistryCoreProperties.java | 9 ++ .../registry/TicketRegistryProperties.java | 7 - .../amqp/AMQPTicketRegistryProperties.java | 43 ------ .../amqp-ticket-registry/script.json | 8 +- ci/tests/syncope/run-syncope-server.sh | 2 +- .../AbstractMapBasedTicketRegistry.java | 77 ++++++++-- .../registry/CachingTicketRegistry.java | 15 +- .../registry/DefaultTicketRegistry.java | 14 +- ...ueueableTicketRegistryMessageReceiver.java | 16 ++ ...ssageQueueMessageSerializationHandler.java | 8 +- .../pubsub/QueueableTicketRegistry.java | 7 +- .../AddTicketMessageQueueCommand.java | 6 +- .../commands/BaseMessageQueueCommand.java | 6 +- .../DeleteTicketMessageQueueCommand.java | 6 +- .../DeleteTicketsMessageQueueCommand.java | 6 +- .../UpdateTicketMessageQueueCommand.java | 6 +- ...ueueableTicketRegistryMessageReceiver.java | 19 +-- ...eueableTicketRegistryMessagePublisher.java | 44 ++++++ ...ueueableTicketRegistryMessageReceiver.java | 30 ++++ .../config/CasCoreTicketsConfiguration.java | 141 ++++++++++++++---- .../registry/CachingTicketRegistryTests.java | 5 +- .../ticketing/Default-Ticket-Registry.md | 19 ++- .../Messaging-AMQP-Ticket-Registry.md | 3 +- .../AMQPTicketRegistryConfiguration.java | 72 ++------- ...ketRegistryTicketCatalogConfiguration.java | 33 ---- .../registry/AMQPDefaultTicketRegistry.java | 93 ------------ .../AMQPTicketRegistryQueueReceiver.java | 16 -- .../AMQPTicketRegistryQueuePublisher.java | 9 +- .../queue/TicketRegistryQueuePublisher.java | 19 --- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../AMQPDefaultTicketRegistryTests.java | 8 +- .../AMQPTicketRegistryQueueReceiverTests.java | 5 +- ...bstractTicketMessageQueueCommandTests.java | 4 +- .../AddTicketMessageQueueCommandTests.java | 2 +- .../DeleteTicketMessageQueueCommandTests.java | 2 +- ...DeleteTicketsMessageQueueCommandTests.java | 2 +- .../UpdateTicketMessageQueueCommandTests.java | 2 +- 37 files changed, 382 insertions(+), 383 deletions(-) delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/amqp/AMQPTicketRegistryProperties.java create mode 100644 core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/DefaultQueueableTicketRegistryMessageReceiver.java rename support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPMessageSerializationHandler.java => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/MessageQueueMessageSerializationHandler.java (83%) rename support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistry.java => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/QueueableTicketRegistry.java (78%) rename {support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub}/commands/AddTicketMessageQueueCommand.java (84%) rename {support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub}/commands/BaseMessageQueueCommand.java (79%) rename {support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub}/commands/DeleteTicketMessageQueueCommand.java (85%) rename {support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub}/commands/DeleteTicketsMessageQueueCommand.java (84%) rename {support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub}/commands/UpdateTicketMessageQueueCommand.java (84%) rename support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/BaseTicketRegistryQueueReceiver.java => core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/BaseQueueableTicketRegistryMessageReceiver.java (63%) create mode 100644 core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessagePublisher.java create mode 100644 core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessageReceiver.java delete mode 100644 support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryTicketCatalogConfiguration.java delete mode 100644 support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistry.java delete mode 100644 support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiver.java delete mode 100644 support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/TicketRegistryQueuePublisher.java diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryCoreProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryCoreProperties.java index 94ec6a8c6b26..770caa45fac4 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryCoreProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryCoreProperties.java @@ -33,4 +33,13 @@ public class TicketRegistryCoreProperties implements Serializable { * separate from the registry technology itself. */ private boolean enableLocking = true; + + /** + * Identifier for this CAS server node + * that tags the sender/receiver in the queue + * and avoid processing of inbound calls. + * If left blank, an identifier is generated automatically + * and kept in memory. + */ + private String queueIdentifier; } diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java index d6dfb00c1a20..fed53704ddd6 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java @@ -1,6 +1,5 @@ package org.apereo.cas.configuration.model.core.ticket.registry; -import org.apereo.cas.configuration.model.support.amqp.AMQPTicketRegistryProperties; import org.apereo.cas.configuration.model.support.cassandra.ticketregistry.CassandraTicketRegistryProperties; import org.apereo.cas.configuration.model.support.cosmosdb.CosmosDbTicketRegistryProperties; import org.apereo.cas.configuration.model.support.couchdb.ticketregistry.CouchDbTicketRegistryProperties; @@ -43,12 +42,6 @@ public class TicketRegistryProperties implements Serializable { @NestedConfigurationProperty private CosmosDbTicketRegistryProperties cosmosDb = new CosmosDbTicketRegistryProperties(); - /** - * AMQP registry settings. - */ - @NestedConfigurationProperty - private AMQPTicketRegistryProperties amqp = new AMQPTicketRegistryProperties(); - /** * DynamoDb registry settings. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/amqp/AMQPTicketRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/amqp/AMQPTicketRegistryProperties.java deleted file mode 100644 index 45014ec0e1a1..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/amqp/AMQPTicketRegistryProperties.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.apereo.cas.configuration.model.support.amqp; - -import org.apereo.cas.configuration.model.core.util.EncryptionRandomizedSigningJwtCryptographyProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.springframework.boot.context.properties.NestedConfigurationProperty; - -import java.io.Serial; -import java.io.Serializable; - -/** - * This is {@link AMQPTicketRegistryProperties}. - * - * @author Misagh Moayyed - * @since 5.2.0 - */ -@RequiresModule(name = "cas-server-support-amqp-ticket-registry") -@Getter -@Setter -@Accessors(chain = true) -public class AMQPTicketRegistryProperties implements Serializable { - - @Serial - private static final long serialVersionUID = -2600525447128979994L; - - /** - * Identifier for this CAS server node - * that tags the sender/receiver in the queue - * and avoid processing of inbound calls. - * If left blank, an identifier is generated automatically - * and kept in memory. - */ - private String queueIdentifier; - - /** - * Crypto settings for the registry. - */ - @NestedConfigurationProperty - private EncryptionRandomizedSigningJwtCryptographyProperties crypto = new EncryptionRandomizedSigningJwtCryptographyProperties(); -} diff --git a/ci/tests/puppeteer/scenarios/amqp-ticket-registry/script.json b/ci/tests/puppeteer/scenarios/amqp-ticket-registry/script.json index 1a0aa718aaaa..9fcc69235bb7 100644 --- a/ci/tests/puppeteer/scenarios/amqp-ticket-registry/script.json +++ b/ci/tests/puppeteer/scenarios/amqp-ticket-registry/script.json @@ -19,8 +19,8 @@ "--spring.rabbitmq.username=rabbituser", "--spring.rabbitmq.password=bugsbunny", - "--cas.ticket.registry.amqp.crypto.signing.key=CYPAXgmLzDnPjWEdCMeP360LorQjurUFtUgJGvBLdctpGgUDK1NjTnfjEmHJpnQHwQ52KYWpmQ4GlAmsxlDjiQ", - "--cas.ticket.registry.amqp.crypto.encryption.key=7CITiW3O2dOpUYOwHJX3-w", + "--cas.ticket.registry.in-memory.crypto.signing.key=CYPAXgmLzDnPjWEdCMeP360LorQjurUFtUgJGvBLdctpGgUDK1NjTnfjEmHJpnQHwQ52KYWpmQ4GlAmsxlDjiQ", + "--cas.ticket.registry.in-memory.crypto.encryption.key=7CITiW3O2dOpUYOwHJX3-w", "--cas.authn.pac4j.saml[0].keystore-password=pac4j-demo-passwd", "--cas.authn.pac4j.saml[0].private-key-password=pac4j-demo-passwd", @@ -39,12 +39,12 @@ "instances": 2, "instance1": { "properties": [ - "--cas.ticket.registry.amqp.queue-identifier=cas-jms-queue-1" + "--cas.ticket.registry.core.queue-identifier=cas-queue-1" ] }, "instance2": { "properties": [ - "--cas.ticket.registry.amqp.queue-identifier=cas-jms-queue-2" + "--cas.ticket.registry.core.queue-identifier=cas-queue-2" ] } } diff --git a/ci/tests/syncope/run-syncope-server.sh b/ci/tests/syncope/run-syncope-server.sh index ab8181a2c856..63b26c3d740c 100644 --- a/ci/tests/syncope/run-syncope-server.sh +++ b/ci/tests/syncope/run-syncope-server.sh @@ -7,7 +7,7 @@ docker-compose -f $COMPOSE_FILE down >/dev/null 2>/dev/null || true docker-compose -f $COMPOSE_FILE up -d docker logs syncope-syncope-1 -f & echo -e "Waiting for Syncope server to come online...\n" -sleep 30 +sleep 60 until $(curl --output /dev/null --silent --head --fail http://localhost:18080/syncope/); do printf '.' sleep 1 diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractMapBasedTicketRegistry.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractMapBasedTicketRegistry.java index c2f46d0522e9..ed22f8503d4a 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractMapBasedTicketRegistry.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractMapBasedTicketRegistry.java @@ -2,7 +2,14 @@ import org.apereo.cas.ticket.Ticket; import org.apereo.cas.ticket.TicketCatalog; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.commands.AddTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.DeleteTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.DeleteTicketsMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.UpdateTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; import org.apereo.cas.ticket.serialization.TicketSerializationManager; +import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.crypto.CipherExecutor; import lombok.extern.slf4j.Slf4j; @@ -20,12 +27,20 @@ * @since 5.2.0 */ @Slf4j -public abstract class AbstractMapBasedTicketRegistry extends AbstractTicketRegistry { +public abstract class AbstractMapBasedTicketRegistry extends AbstractTicketRegistry implements QueueableTicketRegistry { + + protected final QueueableTicketRegistryMessagePublisher ticketPublisher; + + protected final PublisherIdentifier publisherIdentifier; public AbstractMapBasedTicketRegistry(final CipherExecutor cipherExecutor, final TicketSerializationManager ticketSerializationManager, - final TicketCatalog ticketCatalog) { + final TicketCatalog ticketCatalog, + final QueueableTicketRegistryMessagePublisher ticketPublisher, + final PublisherIdentifier publisherIdentifier) { super(cipherExecutor, ticketSerializationManager, ticketCatalog); + this.ticketPublisher = ticketPublisher; + this.publisherIdentifier = publisherIdentifier; } @Override @@ -50,9 +65,11 @@ public Ticket getTicket(final String ticketId, final Predicate predicate @Override public long deleteAll() { - val size = getMapInstance().size(); - getMapInstance().clear(); - return size; + val result = deleteAllFromQueue(); + if (ticketPublisher.isEnabled()) { + ticketPublisher.publishMessageToQueue(new DeleteTicketsMessageQueueCommand(publisherIdentifier)); + } + return result; } @Override @@ -62,24 +79,64 @@ public Collection getTickets() { @Override public Ticket updateTicket(final Ticket ticket) throws Exception { - LOGGER.trace("Updating ticket [{}] in registry...", ticket.getId()); - addTicket(ticket); - return ticket; + val result = updateTicketInQueue(ticket); + + if (ticketPublisher.isEnabled()) { + LOGGER.trace("Publishing update command for id [{}] and ticket [{}]", publisherIdentifier, ticket.getId()); + val command = new UpdateTicketMessageQueueCommand(publisherIdentifier, ticket); + ticketPublisher.publishMessageToQueue(command); + } + return result; } @Override public long deleteSingleTicket(final String ticketId) { - val encTicketId = digest(ticketId); - return !StringUtils.isBlank(encTicketId) && getMapInstance().remove(encTicketId) != null ? 1 : 0; + val result = deleteTicketFromQueue(ticketId); + if (ticketPublisher.isEnabled()) { + LOGGER.trace("Publishing delete command for id [{}] and ticket [{}]", publisherIdentifier, ticketId); + ticketPublisher.publishMessageToQueue(new DeleteTicketMessageQueueCommand(publisherIdentifier, ticketId)); + } + return result; } @Override public void addTicketInternal(final Ticket ticket) throws Exception { + addTicketToQueue(ticket); + + if (ticketPublisher.isEnabled()) { + LOGGER.trace("Publishing add command for id [{}] and ticket [{}]", publisherIdentifier, ticket.getId()); + val command = new AddTicketMessageQueueCommand(publisherIdentifier, ticket); + ticketPublisher.publishMessageToQueue(command); + } + } + + @Override + public void addTicketToQueue(final Ticket ticket) throws Exception { val encTicket = encodeTicket(ticket); LOGGER.debug("Putting ticket [{}] in registry.", ticket.getId()); getMapInstance().put(encTicket.getId(), encTicket); } + @Override + public Ticket updateTicketInQueue(final Ticket ticket) throws Exception { + LOGGER.trace("Updating ticket [{}] in registry...", ticket.getId()); + addTicket(ticket); + return ticket; + } + + @Override + public long deleteTicketFromQueue(final String ticketId) { + val encTicketId = digest(ticketId); + return !StringUtils.isBlank(encTicketId) && getMapInstance().remove(encTicketId) != null ? 1 : 0; + } + + @Override + public long deleteAllFromQueue() { + val size = getMapInstance().size(); + getMapInstance().clear(); + return size; + } + /** * Create map instance, which must ben created during initialization phases * and always be the same instance. diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/CachingTicketRegistry.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/CachingTicketRegistry.java index 51b96133f6c2..ad7bacdd0b09 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/CachingTicketRegistry.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/CachingTicketRegistry.java @@ -5,7 +5,9 @@ import org.apereo.cas.ticket.Ticket; import org.apereo.cas.ticket.TicketCatalog; import org.apereo.cas.ticket.TicketGrantingTicket; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; import org.apereo.cas.ticket.serialization.TicketSerializationManager; +import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.crypto.CipherExecutor; import com.github.benmanes.caffeine.cache.Cache; @@ -42,15 +44,20 @@ public class CachingTicketRegistry extends AbstractMapBasedTicketRegistry { public CachingTicketRegistry( final TicketSerializationManager ticketSerializationManager, final TicketCatalog ticketCatalog, - final ObjectProvider logoutManager) { - this(CipherExecutor.noOp(), ticketSerializationManager, ticketCatalog, logoutManager); + final ObjectProvider logoutManager, + final QueueableTicketRegistryMessagePublisher ticketPublisher, + final PublisherIdentifier publisherIdentifier) { + this(CipherExecutor.noOp(), ticketSerializationManager, ticketCatalog, + logoutManager, ticketPublisher, publisherIdentifier); } public CachingTicketRegistry(final CipherExecutor cipherExecutor, final TicketSerializationManager ticketSerializationManager, final TicketCatalog ticketCatalog, - final ObjectProvider logoutManager) { - super(cipherExecutor, ticketSerializationManager, ticketCatalog); + final ObjectProvider logoutManager, + final QueueableTicketRegistryMessagePublisher ticketPublisher, + final PublisherIdentifier publisherIdentifier) { + super(cipherExecutor, ticketSerializationManager, ticketCatalog, ticketPublisher, publisherIdentifier); this.storage = Caffeine.newBuilder() .initialCapacity(INITIAL_CACHE_SIZE) .maximumSize(MAX_CACHE_SIZE) diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/DefaultTicketRegistry.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/DefaultTicketRegistry.java index 28b3c2e75480..9c16c9e304fc 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/DefaultTicketRegistry.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/DefaultTicketRegistry.java @@ -2,7 +2,9 @@ import org.apereo.cas.ticket.Ticket; import org.apereo.cas.ticket.TicketCatalog; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; import org.apereo.cas.ticket.serialization.TicketSerializationManager; +import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.crypto.CipherExecutor; import lombok.Getter; @@ -19,9 +21,6 @@ @Getter public class DefaultTicketRegistry extends AbstractMapBasedTicketRegistry { - /** - * A map to contain the tickets. - */ private final Map mapInstance; public DefaultTicketRegistry(final TicketSerializationManager ticketSerializationManager, @@ -32,14 +31,17 @@ public DefaultTicketRegistry(final TicketSerializationManager ticketSerializatio public DefaultTicketRegistry(final CipherExecutor cipherExecutor, final TicketSerializationManager ticketSerializationManager, final TicketCatalog ticketCatalog) { - this(cipherExecutor, ticketSerializationManager, ticketCatalog, new ConcurrentHashMap<>()); + this(cipherExecutor, ticketSerializationManager, ticketCatalog, + new ConcurrentHashMap<>(), QueueableTicketRegistryMessagePublisher.noOp(), new PublisherIdentifier()); } public DefaultTicketRegistry(final CipherExecutor cipherExecutor, final TicketSerializationManager ticketSerializationManager, final TicketCatalog ticketCatalog, - final Map storageMap) { - super(cipherExecutor, ticketSerializationManager, ticketCatalog); + final Map storageMap, + final QueueableTicketRegistryMessagePublisher ticketPublisher, + final PublisherIdentifier publisherIdentifier) { + super(cipherExecutor, ticketSerializationManager, ticketCatalog, ticketPublisher, publisherIdentifier); this.mapInstance = storageMap; } } diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/DefaultQueueableTicketRegistryMessageReceiver.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/DefaultQueueableTicketRegistryMessageReceiver.java new file mode 100644 index 000000000000..967f0e6fc2c0 --- /dev/null +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/DefaultQueueableTicketRegistryMessageReceiver.java @@ -0,0 +1,16 @@ +package org.apereo.cas.ticket.registry.pubsub; + +import org.apereo.cas.ticket.registry.pubsub.queue.BaseQueueableTicketRegistryMessageReceiver; +import org.apereo.cas.util.PublisherIdentifier; + +/** + * This is {@link DefaultQueueableTicketRegistryMessageReceiver}. + * + * @author Misagh Moayyed + * @since 5.2.0 + */ +public class DefaultQueueableTicketRegistryMessageReceiver extends BaseQueueableTicketRegistryMessageReceiver { + public DefaultQueueableTicketRegistryMessageReceiver(final QueueableTicketRegistry ticketRegistry, final PublisherIdentifier ticketRegistryId) { + super(ticketRegistry, ticketRegistryId); + } +} diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPMessageSerializationHandler.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/MessageQueueMessageSerializationHandler.java similarity index 83% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPMessageSerializationHandler.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/MessageQueueMessageSerializationHandler.java index a3ea8e317015..cec48fd85a19 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPMessageSerializationHandler.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/MessageQueueMessageSerializationHandler.java @@ -1,6 +1,6 @@ -package org.apereo.cas.ticket.registry; +package org.apereo.cas.ticket.registry.pubsub; -import org.apereo.cas.ticket.registry.queue.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; import org.apereo.cas.util.crypto.CipherExecutor; import org.apereo.cas.util.serialization.SerializationUtils; @@ -16,13 +16,13 @@ import java.io.Serializable; /** - * This is {@link AMQPMessageSerializationHandler}. + * This is {@link MessageQueueMessageSerializationHandler}. * * @author Misagh Moayyed * @since 7.0.0 */ @RequiredArgsConstructor -public class AMQPMessageSerializationHandler implements Serializer, Deserializer { +public class MessageQueueMessageSerializationHandler implements Serializer, Deserializer { private final CipherExecutor cipher; @Override diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistry.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/QueueableTicketRegistry.java similarity index 78% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistry.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/QueueableTicketRegistry.java index 50e3b32217d9..b4247fcdb7a0 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistry.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/QueueableTicketRegistry.java @@ -1,14 +1,15 @@ -package org.apereo.cas.ticket.registry; +package org.apereo.cas.ticket.registry.pubsub; import org.apereo.cas.ticket.Ticket; +import org.apereo.cas.ticket.registry.TicketRegistry; /** - * This is {@link AMQPTicketRegistry}. + * This is {@link QueueableTicketRegistry}. * * @author Misagh Moayyed * @since 7.0.0 */ -public interface AMQPTicketRegistry extends TicketRegistry { +public interface QueueableTicketRegistry extends TicketRegistry { /** * Add ticket to queue. diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/AddTicketMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java similarity index 84% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/AddTicketMessageQueueCommand.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java index 538d8991e097..51ce440fbe70 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/AddTicketMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java @@ -1,7 +1,7 @@ -package org.apereo.cas.ticket.registry.queue.commands; +package org.apereo.cas.ticket.registry.pubsub.commands; import org.apereo.cas.ticket.Ticket; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -33,7 +33,7 @@ public AddTicketMessageQueueCommand(final PublisherIdentifier id, final Ticket t } @Override - public void execute(final AMQPTicketRegistry registry) throws Exception { + public void execute(final QueueableTicketRegistry registry) throws Exception { LOGGER.debug("Executing queue command on ticket registry id [{}] to add ticket [{}]", getId().getId(), ticket); registry.addTicketToQueue(this.ticket); } diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/BaseMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/BaseMessageQueueCommand.java similarity index 79% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/BaseMessageQueueCommand.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/BaseMessageQueueCommand.java index 8d9fcae7612f..700976c3a176 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/BaseMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/BaseMessageQueueCommand.java @@ -1,6 +1,6 @@ -package org.apereo.cas.ticket.registry.queue.commands; +package org.apereo.cas.ticket.registry.pubsub.commands; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -38,5 +38,5 @@ public abstract class BaseMessageQueueCommand implements Serializable { * @param registry the registry * @throws Exception the exception */ - public abstract void execute(AMQPTicketRegistry registry) throws Exception; + public abstract void execute(QueueableTicketRegistry registry) throws Exception; } diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/DeleteTicketMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java similarity index 85% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/DeleteTicketMessageQueueCommand.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java index 61dd881e08f5..fef055e89a24 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/DeleteTicketMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java @@ -1,6 +1,6 @@ -package org.apereo.cas.ticket.registry.queue.commands; +package org.apereo.cas.ticket.registry.pubsub.commands; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonCreator; @@ -36,7 +36,7 @@ public DeleteTicketMessageQueueCommand(final PublisherIdentifier id, } @Override - public void execute(final AMQPTicketRegistry registry) throws Exception { + public void execute(final QueueableTicketRegistry registry) throws Exception { LOGGER.debug("Executing queue command on ticket registry id [{}] to delete ticket [{}]", getId().getId(), ticketId); registry.deleteTicketFromQueue(this.ticketId); } diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/DeleteTicketsMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java similarity index 84% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/DeleteTicketsMessageQueueCommand.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java index b87831f0d698..a887494dea28 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/DeleteTicketsMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java @@ -1,6 +1,6 @@ -package org.apereo.cas.ticket.registry.queue.commands; +package org.apereo.cas.ticket.registry.pubsub.commands; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonCreator; @@ -29,7 +29,7 @@ public DeleteTicketsMessageQueueCommand(final PublisherIdentifier id) { } @Override - public void execute(final AMQPTicketRegistry registry) { + public void execute(final QueueableTicketRegistry registry) { LOGGER.debug("Executing queue command on ticket registry id [{}] to delete tickets", getId().getId()); registry.deleteAllFromQueue(); } diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/UpdateTicketMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java similarity index 84% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/UpdateTicketMessageQueueCommand.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java index 3203dfb0e71b..a26f78804f58 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/commands/UpdateTicketMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java @@ -1,7 +1,7 @@ -package org.apereo.cas.ticket.registry.queue.commands; +package org.apereo.cas.ticket.registry.pubsub.commands; import org.apereo.cas.ticket.Ticket; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -33,7 +33,7 @@ public UpdateTicketMessageQueueCommand(final PublisherIdentifier id, final Ticke } @Override - public void execute(final AMQPTicketRegistry registry) throws Exception { + public void execute(final QueueableTicketRegistry registry) throws Exception { LOGGER.debug("Executing queue command on ticket registry id [{}] to update ticket [{}]", getId().getId(), ticket); registry.updateTicketInQueue(this.ticket); } diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/BaseTicketRegistryQueueReceiver.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/BaseQueueableTicketRegistryMessageReceiver.java similarity index 63% rename from support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/BaseTicketRegistryQueueReceiver.java rename to core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/BaseQueueableTicketRegistryMessageReceiver.java index 1b8427db75b8..6a8e765bd556 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/BaseTicketRegistryQueueReceiver.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/BaseQueueableTicketRegistryMessageReceiver.java @@ -1,7 +1,7 @@ -package org.apereo.cas.ticket.registry.queue; +package org.apereo.cas.ticket.registry.pubsub.queue; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; -import org.apereo.cas.ticket.registry.queue.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; import org.apereo.cas.util.PublisherIdentifier; import lombok.Getter; @@ -9,7 +9,7 @@ import lombok.extern.slf4j.Slf4j; /** - * This is {@link BaseTicketRegistryQueueReceiver}. + * This is {@link BaseQueueableTicketRegistryMessageReceiver}. * * @author Misagh Moayyed * @since 6.5.0 @@ -17,17 +17,12 @@ @Slf4j @RequiredArgsConstructor @Getter -public abstract class BaseTicketRegistryQueueReceiver { - private final AMQPTicketRegistry ticketRegistry; +public abstract class BaseQueueableTicketRegistryMessageReceiver implements QueueableTicketRegistryMessageReceiver { + private final QueueableTicketRegistry ticketRegistry; private final PublisherIdentifier ticketRegistryId; - /** - * Receive message from queue and execute command. - * - * @param command the command - * @throws Exception the exception - */ + @Override public void receive(final BaseMessageQueueCommand command) throws Exception { LOGGER.debug("[{}] received message [{}]", ticketRegistryId, command); if (command.getId().equals(this.ticketRegistryId)) { diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessagePublisher.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessagePublisher.java new file mode 100644 index 000000000000..43b4b2da0907 --- /dev/null +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessagePublisher.java @@ -0,0 +1,44 @@ +package org.apereo.cas.ticket.registry.pubsub.queue; + +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; + +/** + * This is {@link QueueableTicketRegistryMessagePublisher}. + * + * @author Misagh Moayyed + * @since 6.1.0 + */ +public interface QueueableTicketRegistryMessagePublisher { + + /** + * No op ticket registry message publisher + * that does nothing and disables the publisher. + * + * @return the queueable ticket registry message publisher + */ + static QueueableTicketRegistryMessagePublisher noOp() { + return new QueueableTicketRegistryMessagePublisher() { + @Override + public boolean isEnabled() { + return false; + } + }; + } + + /** + * Publish message to queue. + * Default implementation is do nothing. + * @param cmd the cmd + */ + default void publishMessageToQueue(BaseMessageQueueCommand cmd) { + } + + /** + * Is publishing enabled? + * + * @return true/false + */ + default boolean isEnabled() { + return true; + } +} diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessageReceiver.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessageReceiver.java new file mode 100644 index 000000000000..266ed0a07441 --- /dev/null +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/queue/QueueableTicketRegistryMessageReceiver.java @@ -0,0 +1,30 @@ +package org.apereo.cas.ticket.registry.pubsub.queue; + +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; + +/** + * This is {@link QueueableTicketRegistryMessageReceiver}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@FunctionalInterface +public interface QueueableTicketRegistryMessageReceiver { + + /** + * No op queueable ticket registry message receiver that does nothing. + * + * @return the queueable ticket registry message receiver + */ + static QueueableTicketRegistryMessageReceiver noOp() { + return command -> { + }; + } + /** + * Receive message from queue and execute command. + * + * @param command the command + * @throws Exception the exception + */ + void receive(BaseMessageQueueCommand command) throws Exception; +} diff --git a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsConfiguration.java b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsConfiguration.java index cf53d9837882..a36cbbe9f74a 100644 --- a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsConfiguration.java +++ b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsConfiguration.java @@ -39,14 +39,20 @@ import org.apereo.cas.ticket.registry.DefaultTicketRegistrySupport; import org.apereo.cas.ticket.registry.TicketRegistry; import org.apereo.cas.ticket.registry.TicketRegistrySupport; +import org.apereo.cas.ticket.registry.pubsub.DefaultQueueableTicketRegistryMessageReceiver; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessageReceiver; import org.apereo.cas.ticket.serialization.TicketSerializationManager; import org.apereo.cas.util.CoreTicketUtils; import org.apereo.cas.util.ProxyGrantingTicketIdGenerator; import org.apereo.cas.util.ProxyTicketIdGenerator; +import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.TicketGrantingTicketIdGenerator; import org.apereo.cas.util.cipher.CipherExecutorUtils; import org.apereo.cas.util.cipher.ProtocolTicketCipherExecutor; import org.apereo.cas.util.crypto.CipherExecutor; +import org.apereo.cas.util.function.FunctionUtils; import org.apereo.cas.util.lock.LockRepository; import org.apereo.cas.util.spring.beans.BeanCondition; import org.apereo.cas.util.spring.beans.BeanSupplier; @@ -65,6 +71,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.Ordered; import org.springframework.scheduling.annotation.EnableAsync; @@ -98,7 +105,8 @@ public static class CasCoreTicketsBaseConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public ServiceTicketSessionTrackingPolicy serviceTicketSessionTrackingPolicy( - @Qualifier(TicketRegistry.BEAN_NAME) final TicketRegistry ticketRegistry, + @Qualifier(TicketRegistry.BEAN_NAME) + final TicketRegistry ticketRegistry, final CasConfigurationProperties casProperties) { return new DefaultServiceTicketSessionTrackingPolicy(casProperties, ticketRegistry); } @@ -107,7 +115,8 @@ public ServiceTicketSessionTrackingPolicy serviceTicketSessionTrackingPolicy( @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketRegistrySupport defaultTicketRegistrySupport( - @Qualifier(TicketRegistry.BEAN_NAME) final TicketRegistry ticketRegistry) { + @Qualifier(TicketRegistry.BEAN_NAME) + final TicketRegistry ticketRegistry) { return new DefaultTicketRegistrySupport(ticketRegistry); } } @@ -119,7 +128,8 @@ public static class CasCoreTicketsAuthenticationPlanConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public AuthenticationEventExecutionPlanConfigurer ticketAuthenticationPolicyExecutionPlanConfigurer( - @Qualifier(TicketRegistry.BEAN_NAME) final TicketRegistry ticketRegistry, + @Qualifier(TicketRegistry.BEAN_NAME) + final TicketRegistry ticketRegistry, final CasConfigurationProperties casProperties) { return plan -> { val policyProps = casProperties.getAuthn().getPolicy(); @@ -139,6 +149,12 @@ public static class CasCoreTicketRegistryConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketRegistry ticketRegistry( + @Qualifier("messageQueueTicketRegistryPublisher") + final QueueableTicketRegistryMessagePublisher messageQueueTicketRegistryPublisher, + @Qualifier("defaultTicketRegistryCipherExecutor") + final CipherExecutor defaultTicketRegistryCipherExecutor, + @Qualifier("messageQueueTicketRegistryIdentifier") + final PublisherIdentifier messageQueueTicketRegistryIdentifier, @Qualifier(TicketCatalog.BEAN_NAME) final TicketCatalog ticketCatalog, @Qualifier(TicketSerializationManager.BEAN_NAME) @@ -149,13 +165,52 @@ public TicketRegistry ticketRegistry( LOGGER.info("Runtime memory is used as the persistence storage for retrieving and managing tickets. " + "Tickets that are issued during runtime will be LOST when the web server is restarted. This MAY impact SSO functionality."); val mem = casProperties.getTicket().getRegistry().getInMemory(); - val cipher = CoreTicketUtils.newTicketRegistryCipherExecutor(mem.getCrypto(), "in-memory"); - if (mem.isCache()) { - return new CachingTicketRegistry(cipher, ticketSerializationManager, ticketCatalog, logoutManager); + return new CachingTicketRegistry(defaultTicketRegistryCipherExecutor, ticketSerializationManager, ticketCatalog, + logoutManager, messageQueueTicketRegistryPublisher, messageQueueTicketRegistryIdentifier); } val storageMap = new ConcurrentHashMap(mem.getInitialCapacity(), mem.getLoadFactor(), mem.getConcurrency()); - return new DefaultTicketRegistry(cipher, ticketSerializationManager, ticketCatalog, storageMap); + return new DefaultTicketRegistry(defaultTicketRegistryCipherExecutor, ticketSerializationManager, ticketCatalog, + storageMap, messageQueueTicketRegistryPublisher, messageQueueTicketRegistryIdentifier); + } + + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @ConditionalOnMissingBean(name = "defaultTicketRegistryCipherExecutor") + public CipherExecutor defaultTicketRegistryCipherExecutor(final CasConfigurationProperties casProperties) { + val mem = casProperties.getTicket().getRegistry().getInMemory(); + return CoreTicketUtils.newTicketRegistryCipherExecutor(mem.getCrypto(), "in-memory"); + } + + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @ConditionalOnMissingBean(name = "messageQueueTicketRegistryPublisher") + public QueueableTicketRegistryMessagePublisher messageQueueTicketRegistryPublisher() { + return QueueableTicketRegistryMessagePublisher.noOp(); + } + + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @ConditionalOnMissingBean(name = "messageQueueTicketRegistryReceiver") + @Lazy(false) + public QueueableTicketRegistryMessageReceiver messageQueueTicketRegistryReceiver( + @Qualifier(TicketRegistry.BEAN_NAME) + final TicketRegistry ticketRegistry, + @Qualifier("messageQueueTicketRegistryIdentifier") + final PublisherIdentifier messageQueueTicketRegistryIdentifier) { + return ticketRegistry instanceof QueueableTicketRegistry queueableTicketRegistry + ? new DefaultQueueableTicketRegistryMessageReceiver(queueableTicketRegistry, messageQueueTicketRegistryIdentifier) + : QueueableTicketRegistryMessageReceiver.noOp(); + } + + @ConditionalOnMissingBean(name = "messageQueueTicketRegistryIdentifier") + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + public PublisherIdentifier messageQueueTicketRegistryIdentifier(final CasConfigurationProperties casProperties) { + val bean = new PublisherIdentifier(); + val amqp = casProperties.getTicket().getRegistry().getCore(); + FunctionUtils.doIfNotBlank(amqp.getQueueIdentifier(), __ -> bean.setId(amqp.getQueueIdentifier())); + return bean; } @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) @@ -227,7 +282,8 @@ public static class CasCoreProxyGrantingTicketExecutionPlanConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketFactoryExecutionPlanConfigurer defaultProxyGrantingTicketFactoryConfigurer( - @Qualifier("defaultProxyGrantingTicketFactory") final ProxyGrantingTicketFactory defaultProxyGrantingTicketFactory) { + @Qualifier("defaultProxyGrantingTicketFactory") + final ProxyGrantingTicketFactory defaultProxyGrantingTicketFactory) { return () -> defaultProxyGrantingTicketFactory; } } @@ -239,7 +295,8 @@ public static class CasCoreProxyTicketExecutionPlanConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketFactoryExecutionPlanConfigurer defaultProxyTicketFactoryConfigurer( - @Qualifier("defaultProxyTicketFactory") final ProxyTicketFactory defaultProxyTicketFactory) { + @Qualifier("defaultProxyTicketFactory") + final ProxyTicketFactory defaultProxyTicketFactory) { return () -> defaultProxyTicketFactory; } } @@ -251,7 +308,8 @@ public static class CasCoreServiceTicketExecutionPlanConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketFactoryExecutionPlanConfigurer defaultServiceTicketFactoryConfigurer( - @Qualifier("defaultServiceTicketFactory") final ServiceTicketFactory defaultServiceTicketFactory) { + @Qualifier("defaultServiceTicketFactory") + final ServiceTicketFactory defaultServiceTicketFactory) { return () -> defaultServiceTicketFactory; } } @@ -263,7 +321,8 @@ public static class CasCoreTransientSessionTicketExecutionPlanConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketFactoryExecutionPlanConfigurer defaultTransientSessionTicketFactoryConfigurer( - @Qualifier("defaultTransientSessionTicketFactory") final TransientSessionTicketFactory defaultTransientSessionTicketFactory) { + @Qualifier("defaultTransientSessionTicketFactory") + final TransientSessionTicketFactory defaultTransientSessionTicketFactory) { return () -> defaultTransientSessionTicketFactory; } } @@ -275,7 +334,8 @@ public static class CasCoreTicketGrantingTicketExecutionPlanConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketFactoryExecutionPlanConfigurer defaultTicketGrantingTicketFactoryConfigurer( - @Qualifier("defaultTicketGrantingTicketFactory") final TicketGrantingTicketFactory defaultTicketGrantingTicketFactory) { + @Qualifier("defaultTicketGrantingTicketFactory") + final TicketGrantingTicketFactory defaultTicketGrantingTicketFactory) { return () -> defaultTicketGrantingTicketFactory; } } @@ -287,10 +347,14 @@ public static class CasCoreTicketGrantingTicketFactoryConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TicketGrantingTicketFactory defaultTicketGrantingTicketFactory( - @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_TICKET_GRANTING_TICKET_EXPIRATION_POLICY) final ExpirationPolicyBuilder grantingTicketExpirationPolicy, - @Qualifier("protocolTicketCipherExecutor") final CipherExecutor protocolTicketCipherExecutor, - @Qualifier("ticketGrantingTicketUniqueIdGenerator") final UniqueTicketIdGenerator ticketGrantingTicketUniqueIdGenerator, - @Qualifier(ServicesManager.BEAN_NAME) final ServicesManager servicesManager) { + @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_TICKET_GRANTING_TICKET_EXPIRATION_POLICY) + final ExpirationPolicyBuilder grantingTicketExpirationPolicy, + @Qualifier("protocolTicketCipherExecutor") + final CipherExecutor protocolTicketCipherExecutor, + @Qualifier("ticketGrantingTicketUniqueIdGenerator") + final UniqueTicketIdGenerator ticketGrantingTicketUniqueIdGenerator, + @Qualifier(ServicesManager.BEAN_NAME) + final ServicesManager servicesManager) { return new DefaultTicketGrantingTicketFactory(ticketGrantingTicketUniqueIdGenerator, grantingTicketExpirationPolicy, protocolTicketCipherExecutor, servicesManager); } @@ -304,11 +368,16 @@ public static class CasCoreServiceTicketFactoryConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public ServiceTicketFactory defaultServiceTicketFactory( - @Qualifier(ServiceTicketSessionTrackingPolicy.BEAN_NAME) final ServiceTicketSessionTrackingPolicy serviceTicketSessionTrackingPolicy, - @Qualifier("protocolTicketCipherExecutor") final CipherExecutor protocolTicketCipherExecutor, - @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_SERVICE_TICKET_EXPIRATION_POLICY) final ExpirationPolicyBuilder serviceTicketExpirationPolicy, - @Qualifier(ServicesManager.BEAN_NAME) final ServicesManager servicesManager, - @Qualifier("uniqueIdGeneratorsMap") final Map uniqueIdGeneratorsMap) { + @Qualifier(ServiceTicketSessionTrackingPolicy.BEAN_NAME) + final ServiceTicketSessionTrackingPolicy serviceTicketSessionTrackingPolicy, + @Qualifier("protocolTicketCipherExecutor") + final CipherExecutor protocolTicketCipherExecutor, + @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_SERVICE_TICKET_EXPIRATION_POLICY) + final ExpirationPolicyBuilder serviceTicketExpirationPolicy, + @Qualifier(ServicesManager.BEAN_NAME) + final ServicesManager servicesManager, + @Qualifier("uniqueIdGeneratorsMap") + final Map uniqueIdGeneratorsMap) { return new DefaultServiceTicketFactory(serviceTicketExpirationPolicy, uniqueIdGeneratorsMap, serviceTicketSessionTrackingPolicy, protocolTicketCipherExecutor, servicesManager); @@ -329,11 +398,16 @@ public static class CasCoreProxyTicketFactoryConfiguration { @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) @Bean public ProxyTicketFactory defaultProxyTicketFactory( - @Qualifier(ServiceTicketSessionTrackingPolicy.BEAN_NAME) final ServiceTicketSessionTrackingPolicy serviceTicketSessionTrackingPolicy, - @Qualifier("protocolTicketCipherExecutor") final CipherExecutor protocolTicketCipherExecutor, - @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_PROXY_TICKET_EXPIRATION_POLICY) final ExpirationPolicyBuilder proxyTicketExpirationPolicy, - @Qualifier("uniqueIdGeneratorsMap") final Map uniqueIdGeneratorsMap, - @Qualifier(ServicesManager.BEAN_NAME) final ServicesManager servicesManager) { + @Qualifier(ServiceTicketSessionTrackingPolicy.BEAN_NAME) + final ServiceTicketSessionTrackingPolicy serviceTicketSessionTrackingPolicy, + @Qualifier("protocolTicketCipherExecutor") + final CipherExecutor protocolTicketCipherExecutor, + @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_PROXY_TICKET_EXPIRATION_POLICY) + final ExpirationPolicyBuilder proxyTicketExpirationPolicy, + @Qualifier("uniqueIdGeneratorsMap") + final Map uniqueIdGeneratorsMap, + @Qualifier(ServicesManager.BEAN_NAME) + final ServicesManager servicesManager) { return new DefaultProxyTicketFactory(proxyTicketExpirationPolicy, uniqueIdGeneratorsMap, protocolTicketCipherExecutor, serviceTicketSessionTrackingPolicy, servicesManager); } @@ -347,7 +421,8 @@ public static class CasCoreTransientSessionTicketFactoryConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public TransientSessionTicketFactory defaultTransientSessionTicketFactory( - @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_TRANSIENT_SESSION_TICKET_EXPIRATION_POLICY) final ExpirationPolicyBuilder transientSessionTicketExpirationPolicy) { + @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_TRANSIENT_SESSION_TICKET_EXPIRATION_POLICY) + final ExpirationPolicyBuilder transientSessionTicketExpirationPolicy) { return new DefaultTransientSessionTicketFactory(transientSessionTicketExpirationPolicy); } } @@ -359,10 +434,14 @@ public static class CasCoreProxyGrantingTicketFactoryConfiguration { @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public ProxyGrantingTicketFactory defaultProxyGrantingTicketFactory( - @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_PROXY_GRANTING_TICKET_EXPIRATION_POLICY) final ExpirationPolicyBuilder proxyGrantingTicketExpirationPolicy, - @Qualifier("proxyGrantingTicketUniqueIdGenerator") final UniqueTicketIdGenerator proxyGrantingTicketUniqueIdGenerator, - @Qualifier("protocolTicketCipherExecutor") final CipherExecutor protocolTicketCipherExecutor, - @Qualifier(ServicesManager.BEAN_NAME) final ServicesManager servicesManager) { + @Qualifier(ExpirationPolicyBuilder.BEAN_NAME_PROXY_GRANTING_TICKET_EXPIRATION_POLICY) + final ExpirationPolicyBuilder proxyGrantingTicketExpirationPolicy, + @Qualifier("proxyGrantingTicketUniqueIdGenerator") + final UniqueTicketIdGenerator proxyGrantingTicketUniqueIdGenerator, + @Qualifier("protocolTicketCipherExecutor") + final CipherExecutor protocolTicketCipherExecutor, + @Qualifier(ServicesManager.BEAN_NAME) + final ServicesManager servicesManager) { return new DefaultProxyGrantingTicketFactory( proxyGrantingTicketUniqueIdGenerator, proxyGrantingTicketExpirationPolicy, diff --git a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/CachingTicketRegistryTests.java b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/CachingTicketRegistryTests.java index 92e800431682..77ccba8bfe6b 100644 --- a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/CachingTicketRegistryTests.java +++ b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/CachingTicketRegistryTests.java @@ -7,7 +7,9 @@ import org.apereo.cas.ticket.TicketGrantingTicket; import org.apereo.cas.ticket.TicketGrantingTicketImpl; import org.apereo.cas.ticket.expiration.HardTimeoutExpirationPolicy; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; import org.apereo.cas.ticket.serialization.TicketSerializationManager; +import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.crypto.CipherExecutor; import org.apereo.cas.util.spring.DirectObjectProvider; @@ -41,7 +43,8 @@ public void verifyOtherConstructor() { private static TicketRegistry getTicketRegistryInstance() { return new CachingTicketRegistry(CipherExecutor.noOp(), mock(TicketSerializationManager.class), new DefaultTicketCatalog(), - new DirectObjectProvider<>(mock(LogoutManager.class))); + new DirectObjectProvider<>(mock(LogoutManager.class)), + QueueableTicketRegistryMessagePublisher.noOp(), new PublisherIdentifier()); } @RepeatedTest(1) diff --git a/docs/cas-server-documentation/ticketing/Default-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/Default-Ticket-Registry.md index d2382aa51976..09210c5b7dc6 100644 --- a/docs/cas-server-documentation/ticketing/Default-Ticket-Registry.md +++ b/docs/cas-server-documentation/ticketing/Default-Ticket-Registry.md @@ -12,22 +12,31 @@ The default registry uses a memory-backed internal concurrent map for ticket storage and retrieval, though there is also the option to use an implementation that is backed by a caching engine to gain slightly better performance when it comes to evicting expired tickets. -This component does not preserve ticket state across restarts and is not a suitable solution -for clustered CAS environments that are deployed in active/active mode. - {% include_cached casproperties.html properties="cas.ticket.registry.in-memory" %} -### Eviction Policy +## Eviction Policy This ticket registry relies on a background job that is automatically scheduled to clean up after the registry and remove expired tickets. The cleaner will periodically examine the state of the registry to identify expired tickets, remove them from the registry and then execute relevant logout operations. -In the event that the ticket registry is configured to use caching engine, CAS configures +In the event that the ticket registry is configured to use a caching engine, CAS configures the cache store automatically such that each ticket put into the cache is given the ability to automatically expire based on the expiration policies defined for each ticket. The cache is constantly on its own monitoring for eviction events and once an item is deemed expired and evicted, CAS will take over to run logout operations. This means that running the default registry in this mode does not require CAS to schedule and maintain a background job to look after ticket state given the cache cleans up after itself. + +## Clustering + +This registry does not by default preserve ticket state across restarts and is not a suitable solution +for clustered CAS environments that are deployed in active/active mode. Tickets are managed and stored +in the runtime memory that is bound to the CAS server node, which means a ticket object created and managed +by CAS server `A` cannot be found and accepted when a request for the same ticket is received by CAS server `B`. + +The registry does however provide extension points for broadcasting the results of ticket operations. +A *Pub/Sub* type of setup can tap into such extension points to allow the registry to operate in clustered +environments, and to share ticket state across all CAS server nodes keeping them all in sync. +Some ticket registries such as the [AMQP Ticket Registry](Messaging-AMQP-Ticket-Registry.html) are able to do so. diff --git a/docs/cas-server-documentation/ticketing/Messaging-AMQP-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/Messaging-AMQP-Ticket-Registry.md index 548316b2ae3d..d67c273677ae 100644 --- a/docs/cas-server-documentation/ticketing/Messaging-AMQP-Ticket-Registry.md +++ b/docs/cas-server-documentation/ticketing/Messaging-AMQP-Ticket-Registry.md @@ -28,8 +28,7 @@ Support is enabled by including the following dependency in the overlay: ## CAS Configuration -{% include_cached casproperties.html properties="cas.ticket.registry.amqp" -thirdPartyStartsWith="spring.rabbitmq" %} +{% include_cached casproperties.html properties="cas.ticket.registry.in-memory" thirdPartyStartsWith="spring.rabbitmq" %} ## Actuator Endpoints diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryConfiguration.java b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryConfiguration.java index 6c3cc644cbba..51088b672f39 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryConfiguration.java +++ b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryConfiguration.java @@ -2,18 +2,12 @@ import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.ticket.TicketCatalog; -import org.apereo.cas.ticket.registry.AMQPDefaultTicketRegistry; -import org.apereo.cas.ticket.registry.AMQPMessageSerializationHandler; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; -import org.apereo.cas.ticket.registry.AMQPTicketRegistryQueueReceiver; -import org.apereo.cas.ticket.registry.TicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.MessageQueueMessageSerializationHandler; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessageReceiver; import org.apereo.cas.ticket.registry.queue.AMQPTicketRegistryQueuePublisher; -import org.apereo.cas.ticket.serialization.TicketSerializationManager; -import org.apereo.cas.util.CoreTicketUtils; import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.crypto.CipherExecutor; -import org.apereo.cas.util.function.FunctionUtils; import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; import lombok.extern.slf4j.Slf4j; @@ -51,68 +45,30 @@ @ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.TicketRegistry, module = "amqp") @AutoConfiguration public class AMQPTicketRegistryConfiguration { - @ConditionalOnMissingBean(name = "messageQueueTicketRegistryIdentifier") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public PublisherIdentifier messageQueueTicketRegistryIdentifier( - final CasConfigurationProperties casProperties) { - val bean = new PublisherIdentifier(); - val amqp = casProperties.getTicket().getRegistry().getAmqp(); - - FunctionUtils.doIfNotBlank(amqp.getQueueIdentifier(), __ -> bean.setId(amqp.getQueueIdentifier())); - return bean; - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "messageQueueTicketRegistryReceiver") - @Lazy(false) - public AMQPTicketRegistryQueueReceiver messageQueueTicketRegistryReceiver( - @Qualifier(TicketRegistry.BEAN_NAME) - final AMQPTicketRegistry ticketRegistry, - @Qualifier("messageQueueTicketRegistryIdentifier") - final PublisherIdentifier messageQueueTicketRegistryIdentifier) { - return new AMQPTicketRegistryQueueReceiver(ticketRegistry, messageQueueTicketRegistryIdentifier); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "messageQueueCipherExecutor") - public CipherExecutor messageQueueCipherExecutor(final CasConfigurationProperties casProperties) { - val amqp = casProperties.getTicket().getRegistry().getAmqp(); - return CoreTicketUtils.newTicketRegistryCipherExecutor(amqp.getCrypto(), "amqp"); - } - + @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public MessageConverter messageQueueTicketRegistryConverter( - @Qualifier("messageQueueCipherExecutor") - final CipherExecutor messageQueueCipherExecutor) { + @Qualifier("defaultTicketRegistryCipherExecutor") + final CipherExecutor defaultTicketRegistryCipherExecutor) { val converter = new SerializerMessageConverter(); converter.setDefaultCharset(StandardCharsets.UTF_8.name()); - converter.setSerializer(new AMQPMessageSerializationHandler(messageQueueCipherExecutor)); - converter.setDeserializer(new AMQPMessageSerializationHandler(messageQueueCipherExecutor)); + converter.setSerializer(new MessageQueueMessageSerializationHandler(defaultTicketRegistryCipherExecutor)); + converter.setDeserializer(new MessageQueueMessageSerializationHandler(defaultTicketRegistryCipherExecutor)); return converter; } @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AMQPTicketRegistry ticketRegistry( - @Qualifier(TicketCatalog.BEAN_NAME) - final TicketCatalog ticketCatalog, - @Qualifier(TicketSerializationManager.BEAN_NAME) - final TicketSerializationManager ticketSerializationManager, - @Qualifier("messageQueueCipherExecutor") - final CipherExecutor messageQueueCipherExecutor, - final RabbitTemplate rabbitTemplate, + public QueueableTicketRegistryMessagePublisher messageQueueTicketRegistryPublisher( + @Qualifier("messageQueueTicketRegistryIdentifier") + final PublisherIdentifier messageQueueTicketRegistryIdentifier, @Qualifier("messageQueueTicketRegistryConverter") final MessageConverter messageQueueTicketRegistryConverter, - @Qualifier("messageQueueTicketRegistryIdentifier") - final PublisherIdentifier messageQueueTicketRegistryIdentifier) { + final RabbitTemplate rabbitTemplate) { rabbitTemplate.setMessageConverter(messageQueueTicketRegistryConverter); LOGGER.debug("Configuring AMQP ticket registry with identifier [{}]", messageQueueTicketRegistryIdentifier); - return new AMQPDefaultTicketRegistry(messageQueueCipherExecutor, ticketSerializationManager, ticketCatalog, - new AMQPTicketRegistryQueuePublisher(rabbitTemplate), messageQueueTicketRegistryIdentifier); + return new AMQPTicketRegistryQueuePublisher(rabbitTemplate); } @Bean @@ -148,7 +104,7 @@ public MessageListenerContainer amqpTicketRegistryMessageListenerContainer( @Lazy(false) public MessageListenerAdapter amqpTicketRegistryListenerAdapter( @Qualifier("messageQueueTicketRegistryReceiver") - final AMQPTicketRegistryQueueReceiver messageQueueTicketRegistryReceiver, + final QueueableTicketRegistryMessageReceiver messageQueueTicketRegistryReceiver, @Qualifier("messageQueueTicketRegistryConverter") final MessageConverter messageQueueTicketRegistryConverter) { val adapter = new MessageListenerAdapter(messageQueueTicketRegistryReceiver, "receive"); diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryTicketCatalogConfiguration.java b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryTicketCatalogConfiguration.java deleted file mode 100644 index b3ddf0d05309..000000000000 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/config/AMQPTicketRegistryTicketCatalogConfiguration.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.ticket.catalog.CasTicketCatalogConfigurationValuesProvider; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link AMQPTicketRegistryTicketCatalogConfiguration}. - * - * @author Misagh Moayyed - * @since 7.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.TicketRegistry, module = "amqp") -@AutoConfiguration -public class AMQPTicketRegistryTicketCatalogConfiguration { - - @ConditionalOnMissingBean(name = "amqpTicketCatalogConfigurationValuesProvider") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CasTicketCatalogConfigurationValuesProvider amqpTicketCatalogConfigurationValuesProvider() { - return new CasTicketCatalogConfigurationValuesProvider() { - }; - } -} diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistry.java b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistry.java deleted file mode 100644 index b5b9bd6aa941..000000000000 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistry.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.apereo.cas.ticket.registry; - -import org.apereo.cas.ticket.Ticket; -import org.apereo.cas.ticket.TicketCatalog; -import org.apereo.cas.ticket.registry.queue.TicketRegistryQueuePublisher; -import org.apereo.cas.ticket.registry.queue.commands.AddTicketMessageQueueCommand; -import org.apereo.cas.ticket.registry.queue.commands.DeleteTicketMessageQueueCommand; -import org.apereo.cas.ticket.registry.queue.commands.DeleteTicketsMessageQueueCommand; -import org.apereo.cas.ticket.registry.queue.commands.UpdateTicketMessageQueueCommand; -import org.apereo.cas.ticket.serialization.TicketSerializationManager; -import org.apereo.cas.util.PublisherIdentifier; -import org.apereo.cas.util.crypto.CipherExecutor; - -import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; -import lombok.val; - -/** - * This is {@link AMQPDefaultTicketRegistry}. - * - * @author Misagh Moayyed - * @since 5.2.0 - */ -@Slf4j -public class AMQPDefaultTicketRegistry extends DefaultTicketRegistry implements AMQPTicketRegistry { - - private final TicketRegistryQueuePublisher ticketPublisher; - - private final PublisherIdentifier publisherIdentifier; - - public AMQPDefaultTicketRegistry(final CipherExecutor cipherExecutor, - final TicketSerializationManager ticketSerializationManager, - final TicketCatalog ticketCatalog, - final TicketRegistryQueuePublisher ticketPublisher, - final PublisherIdentifier publisherIdentifier) { - super(cipherExecutor, ticketSerializationManager, ticketCatalog); - this.ticketPublisher = ticketPublisher; - this.publisherIdentifier = publisherIdentifier; - } - - @Override - public void addTicketInternal(final @NonNull Ticket ticket) throws Exception { - addTicketToQueue(ticket); - LOGGER.trace("Publishing add command for id [{}] and ticket [{}]", publisherIdentifier, ticket.getId()); - val command = new AddTicketMessageQueueCommand(publisherIdentifier, ticket); - ticketPublisher.publishMessageToQueue(command); - } - - @Override - public Ticket updateTicket(final Ticket ticket) throws Exception { - val result = updateTicketInQueue(ticket); - LOGGER.trace("Publishing update command for id [{}] and ticket [{}]", publisherIdentifier, ticket.getId()); - val command = new UpdateTicketMessageQueueCommand(publisherIdentifier, ticket); - ticketPublisher.publishMessageToQueue(command); - return result; - } - - @Override - public long deleteSingleTicket(final String ticketId) { - val result = deleteTicketFromQueue(ticketId); - LOGGER.trace("Publishing delete command for id [{}] and ticket [{}]", publisherIdentifier, ticketId); - ticketPublisher.publishMessageToQueue(new DeleteTicketMessageQueueCommand(publisherIdentifier, ticketId)); - return result; - } - - @Override - public long deleteAll() { - val result = deleteAllFromQueue(); - ticketPublisher.publishMessageToQueue(new DeleteTicketsMessageQueueCommand(publisherIdentifier)); - return result; - } - - - @Override - public void addTicketToQueue(final Ticket ticket) throws Exception { - super.addTicketInternal(ticket); - } - - @Override - public Ticket updateTicketInQueue(final Ticket ticket) throws Exception { - return super.updateTicket(ticket); - } - - @Override - public long deleteTicketFromQueue(final String ticketId) { - return super.deleteSingleTicket(ticketId); - } - - @Override - public long deleteAllFromQueue() { - return super.deleteAll(); - } -} diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiver.java b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiver.java deleted file mode 100644 index 5eb199fb7675..000000000000 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiver.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.apereo.cas.ticket.registry; - -import org.apereo.cas.ticket.registry.queue.BaseTicketRegistryQueueReceiver; -import org.apereo.cas.util.PublisherIdentifier; - -/** - * This is {@link AMQPTicketRegistryQueueReceiver}. - * - * @author Misagh Moayyed - * @since 5.2.0 - */ -public class AMQPTicketRegistryQueueReceiver extends BaseTicketRegistryQueueReceiver { - public AMQPTicketRegistryQueueReceiver(final AMQPTicketRegistry ticketRegistry, final PublisherIdentifier ticketRegistryId) { - super(ticketRegistry, ticketRegistryId); - } -} diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/AMQPTicketRegistryQueuePublisher.java b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/AMQPTicketRegistryQueuePublisher.java index 2a801582bba2..4fb41e3efb2b 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/AMQPTicketRegistryQueuePublisher.java +++ b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/AMQPTicketRegistryQueuePublisher.java @@ -1,7 +1,9 @@ package org.apereo.cas.ticket.registry.queue; -import org.apereo.cas.ticket.registry.queue.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.amqp.rabbit.core.RabbitOperations; @@ -13,12 +15,15 @@ * @since 6.1.0 */ @Slf4j -public record AMQPTicketRegistryQueuePublisher(RabbitOperations rabbitTemplate) implements TicketRegistryQueuePublisher { +@RequiredArgsConstructor +public class AMQPTicketRegistryQueuePublisher implements QueueableTicketRegistryMessagePublisher { /** * Queue destination name. */ public static final String QUEUE_DESTINATION = "CasTicketRegistryQueue"; + private final RabbitOperations rabbitTemplate; + @Override public void publishMessageToQueue(final BaseMessageQueueCommand cmd) { LOGGER.debug("[{}] is publishing message [{}]", cmd.getId().getId(), cmd); diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/TicketRegistryQueuePublisher.java b/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/TicketRegistryQueuePublisher.java deleted file mode 100644 index 2004a9b43bb4..000000000000 --- a/support/cas-server-support-amqp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/queue/TicketRegistryQueuePublisher.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.apereo.cas.ticket.registry.queue; - -import org.apereo.cas.ticket.registry.queue.commands.BaseMessageQueueCommand; - -/** - * This is {@link TicketRegistryQueuePublisher}. - * - * @author Misagh Moayyed - * @since 6.1.0 - */ -@FunctionalInterface -public interface TicketRegistryQueuePublisher { - /** - * Publish message to queue. - * - * @param cmd the cmd - */ - void publishMessageToQueue(BaseMessageQueueCommand cmd); -} diff --git a/support/cas-server-support-amqp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-amqp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 2f812b350764..d8137d55da21 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/support/cas-server-support-amqp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1 @@ org.apereo.cas.config.AMQPTicketRegistryConfiguration -org.apereo.cas.config.AMQPTicketRegistryTicketCatalogConfiguration diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistryTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistryTests.java index dcacabc50907..ad5eabeef285 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistryTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPDefaultTicketRegistryTests.java @@ -1,7 +1,6 @@ package org.apereo.cas.ticket.registry; import org.apereo.cas.config.AMQPTicketRegistryConfiguration; -import org.apereo.cas.config.AMQPTicketRegistryTicketCatalogConfiguration; import org.apereo.cas.util.crypto.CipherExecutor; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; @@ -28,12 +27,11 @@ AMQPDefaultTicketRegistryTests.AMQPTicketRegistryTestConfiguration.class, CompositeMeterRegistryAutoConfiguration.class, RabbitAutoConfiguration.class, - AMQPTicketRegistryTicketCatalogConfiguration.class, AMQPTicketRegistryConfiguration.class }) @TestPropertySource(properties = { - "cas.ticket.registry.amqp.crypto.signing.key=HbuPoSycjr0Pyv2u8WSwKcM6Ow0lviUdT7b9VzwxkcANqbDyKOb6KHPus_fCDCXElPhzXpeP-T0bryadZNiwOQ", - "cas.ticket.registry.amqp.crypto.encryption.key=BXRiSBWJcRksTizjdaCoLw", + "cas.ticket.registry.amqp.in-memory.signing.key=HbuPoSycjr0Pyv2u8WSwKcM6Ow0lviUdT7b9VzwxkcANqbDyKOb6KHPus_fCDCXElPhzXpeP-T0bryadZNiwOQ", + "cas.ticket.registry.amqp.in-memory.encryption.key=BXRiSBWJcRksTizjdaCoLw", "spring.rabbitmq.host=localhost", "spring.rabbitmq.port=5672", @@ -49,7 +47,7 @@ public class AMQPDefaultTicketRegistryTests extends BaseTicketRegistryTests { private TicketRegistry newTicketRegistry; @Autowired - @Qualifier("messageQueueCipherExecutor") + @Qualifier("defaultTicketRegistryCipherExecutor") private CipherExecutor messageQueueCipherExecutor; @Override diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiverTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiverTests.java index fa064a4715c2..24cabe73a1e3 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiverTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/AMQPTicketRegistryQueueReceiverTests.java @@ -3,8 +3,9 @@ import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.ticket.TicketGrantingTicketImpl; import org.apereo.cas.ticket.expiration.NeverExpiresExpirationPolicy; +import org.apereo.cas.ticket.registry.pubsub.DefaultQueueableTicketRegistryMessageReceiver; +import org.apereo.cas.ticket.registry.pubsub.commands.AddTicketMessageQueueCommand; import org.apereo.cas.ticket.registry.queue.AbstractTicketMessageQueueCommandTests; -import org.apereo.cas.ticket.registry.queue.commands.AddTicketMessageQueueCommand; import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; @@ -27,7 +28,7 @@ public class AMQPTicketRegistryQueueReceiverTests extends AbstractTicketMessageQueueCommandTests { @Test public void verifyOperation() { - val receiver = new AMQPTicketRegistryQueueReceiver(ticketRegistry, + val receiver = new DefaultQueueableTicketRegistryMessageReceiver(ticketRegistry, new PublisherIdentifier(UUID.randomUUID().toString())); var ticket = new TicketGrantingTicketImpl("TGT-334455", CoreAuthenticationTestUtils.getAuthentication(), NeverExpiresExpirationPolicy.INSTANCE); diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AbstractTicketMessageQueueCommandTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AbstractTicketMessageQueueCommandTests.java index 8f5090e79270..b1808f7152ed 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AbstractTicketMessageQueueCommandTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AbstractTicketMessageQueueCommandTests.java @@ -22,8 +22,8 @@ import org.apereo.cas.config.CasPersonDirectoryConfiguration; import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; import org.apereo.cas.logout.config.CasCoreLogoutConfiguration; -import org.apereo.cas.ticket.registry.AMQPTicketRegistry; import org.apereo.cas.ticket.registry.TicketRegistry; +import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.ticket.serialization.TicketSerializationManager; import org.springframework.beans.factory.annotation.Autowired; @@ -79,7 +79,7 @@ public abstract class AbstractTicketMessageQueueCommandTests { @Autowired @Qualifier(TicketRegistry.BEAN_NAME) - protected AMQPTicketRegistry ticketRegistry; + protected QueueableTicketRegistry ticketRegistry; @Autowired @Qualifier(TicketSerializationManager.BEAN_NAME) diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AddTicketMessageQueueCommandTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AddTicketMessageQueueCommandTests.java index 47fd8734732b..9aa5db63fae7 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AddTicketMessageQueueCommandTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/AddTicketMessageQueueCommandTests.java @@ -3,7 +3,7 @@ import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.ticket.TicketGrantingTicketImpl; import org.apereo.cas.ticket.expiration.NeverExpiresExpirationPolicy; -import org.apereo.cas.ticket.registry.queue.commands.AddTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.AddTicketMessageQueueCommand; import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketMessageQueueCommandTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketMessageQueueCommandTests.java index aad0083d27e5..68abca939596 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketMessageQueueCommandTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketMessageQueueCommandTests.java @@ -3,7 +3,7 @@ import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.ticket.TicketGrantingTicketImpl; import org.apereo.cas.ticket.expiration.NeverExpiresExpirationPolicy; -import org.apereo.cas.ticket.registry.queue.commands.DeleteTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.DeleteTicketMessageQueueCommand; import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketsMessageQueueCommandTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketsMessageQueueCommandTests.java index 25b82e30c150..65703ec439c8 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketsMessageQueueCommandTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/DeleteTicketsMessageQueueCommandTests.java @@ -3,7 +3,7 @@ import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.ticket.TicketGrantingTicketImpl; import org.apereo.cas.ticket.expiration.NeverExpiresExpirationPolicy; -import org.apereo.cas.ticket.registry.queue.commands.DeleteTicketsMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.DeleteTicketsMessageQueueCommand; import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; diff --git a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/UpdateTicketMessageQueueCommandTests.java b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/UpdateTicketMessageQueueCommandTests.java index 3a0e66b57e7b..1708177db6a3 100644 --- a/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/UpdateTicketMessageQueueCommandTests.java +++ b/support/cas-server-support-amqp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/queue/UpdateTicketMessageQueueCommandTests.java @@ -3,7 +3,7 @@ import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.ticket.TicketGrantingTicketImpl; import org.apereo.cas.ticket.expiration.NeverExpiresExpirationPolicy; -import org.apereo.cas.ticket.registry.queue.commands.UpdateTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.UpdateTicketMessageQueueCommand; import org.apereo.cas.util.PublisherIdentifier; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; From 14ac7cd319532da865b365ee7766f214828e9d27 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Sat, 11 Mar 2023 13:18:51 +0400 Subject: [PATCH 002/266] support gcp pubsub to broadcast ticket updates --- .../cas/services/AbstractServicesManager.java | 10 ++-- .../AddTicketMessageQueueCommand.java | 10 +++- .../DeleteTicketMessageQueueCommand.java | 7 ++- .../DeleteTicketsMessageQueueCommand.java | 8 ++- .../UpdateTicketMessageQueueCommand.java | 11 ++++- .../release_notes/Overview.md | 1 + .../release_notes/RC5.md | 4 +- .../release_notes/RC6.md | 49 +++++++++++++++++++ .../ticketing/Memcached-Ticket-Registry.md | 3 +- gradle.properties | 1 + gradle/dependencies.gradle | 16 ++++++ settings.gradle | 1 + style/checkstyle-rules.xml | 7 +++ .../build.gradle | 41 ++++++++++++++++ .../GoogleCloudPubSubMessageContext.java | 16 ++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../src/test/resources/log4j2-test.xml | 15 ++++++ 17 files changed, 188 insertions(+), 13 deletions(-) create mode 100644 docs/cas-server-documentation/release_notes/RC6.md create mode 100644 support/cas-server-support-gcp-ticket-registry/build.gradle create mode 100644 support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java create mode 100644 support/cas-server-support-gcp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 support/cas-server-support-gcp-ticket-registry/src/test/resources/log4j2-test.xml diff --git a/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java b/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java index 994b3f3b8636..87b3d8e71cb3 100644 --- a/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java +++ b/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java @@ -172,11 +172,11 @@ public Collection findServiceBy(final Predicate(0); } - val results = configurationContext.getServiceRegistry().findServicePredicate(predicate). - stream(). - sorted(). - peek(RegisteredService::initialize). - collect(Collectors.toMap(RegisteredService::getId, Function.identity(), (r, s) -> s)); + val results = configurationContext.getServiceRegistry().findServicePredicate(predicate) + .stream() + .sorted() + .peek(RegisteredService::initialize) + .collect(Collectors.toMap(RegisteredService::getId, Function.identity(), (r, s) -> s)); configurationContext.getServicesCache().putAll(results); return results.values(); } diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java index 51ce440fbe70..4e1ee2f7c4b5 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/AddTicketMessageQueueCommand.java @@ -4,8 +4,11 @@ import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.Getter; +import lombok.Setter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; @@ -20,6 +23,7 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @Slf4j @Getter +@Setter @ToString(callSuper = true) public class AddTicketMessageQueueCommand extends BaseMessageQueueCommand { @Serial @@ -27,7 +31,11 @@ public class AddTicketMessageQueueCommand extends BaseMessageQueueCommand { private final Ticket ticket; - public AddTicketMessageQueueCommand(final PublisherIdentifier id, final Ticket ticket) { + @JsonCreator + public AddTicketMessageQueueCommand(@JsonProperty("id") + final PublisherIdentifier id, + @JsonProperty("ticket") + final Ticket ticket) { super(id); this.ticket = ticket; } diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java index fef055e89a24..704835015668 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketMessageQueueCommand.java @@ -4,8 +4,10 @@ import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.Getter; +import lombok.Setter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; @@ -20,6 +22,7 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @Slf4j @Getter +@Setter @ToString(callSuper = true) public class DeleteTicketMessageQueueCommand extends BaseMessageQueueCommand { @@ -29,7 +32,9 @@ public class DeleteTicketMessageQueueCommand extends BaseMessageQueueCommand { private final String ticketId; @JsonCreator - public DeleteTicketMessageQueueCommand(final PublisherIdentifier id, + public DeleteTicketMessageQueueCommand(@JsonProperty("id") + final PublisherIdentifier id, + @JsonProperty("ticketId") final String ticketId) { super(id); this.ticketId = ticketId; diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java index a887494dea28..79a2fc111525 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/DeleteTicketsMessageQueueCommand.java @@ -4,7 +4,10 @@ import org.apereo.cas.util.PublisherIdentifier; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import lombok.Getter; +import lombok.Setter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; @@ -19,12 +22,15 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @Slf4j @ToString(callSuper = true) +@Getter +@Setter public class DeleteTicketsMessageQueueCommand extends BaseMessageQueueCommand { @Serial private static final long serialVersionUID = 8907022828993467474L; @JsonCreator - public DeleteTicketsMessageQueueCommand(final PublisherIdentifier id) { + public DeleteTicketsMessageQueueCommand(@JsonProperty("id") + final PublisherIdentifier id) { super(id); } diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java index a26f78804f58..706f48a719f9 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/pubsub/commands/UpdateTicketMessageQueueCommand.java @@ -4,8 +4,11 @@ import org.apereo.cas.ticket.registry.pubsub.QueueableTicketRegistry; import org.apereo.cas.util.PublisherIdentifier; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.Getter; +import lombok.Setter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; @@ -20,6 +23,7 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @Slf4j @Getter +@Setter @ToString(callSuper = true) public class UpdateTicketMessageQueueCommand extends BaseMessageQueueCommand { @Serial @@ -27,7 +31,12 @@ public class UpdateTicketMessageQueueCommand extends BaseMessageQueueCommand { private final Ticket ticket; - public UpdateTicketMessageQueueCommand(final PublisherIdentifier id, final Ticket ticket) { + @JsonCreator + public UpdateTicketMessageQueueCommand( + @JsonProperty("id") + final PublisherIdentifier id, + @JsonProperty("ticket") + final Ticket ticket) { super(id); this.ticket = ticket; } diff --git a/docs/cas-server-documentation/release_notes/Overview.md b/docs/cas-server-documentation/release_notes/Overview.md index d9771e016736..13de73054e3e 100644 --- a/docs/cas-server-documentation/release_notes/Overview.md +++ b/docs/cas-server-documentation/release_notes/Overview.md @@ -11,3 +11,4 @@ category: Planning - [RC3](RC3.html) - [RC4](RC4.html) - [RC5](RC5.html) +- [RC6](RC6.html) diff --git a/docs/cas-server-documentation/release_notes/RC5.md b/docs/cas-server-documentation/release_notes/RC5.md index 6109ac3a92ae..d403e770800c 100644 --- a/docs/cas-server-documentation/release_notes/RC5.md +++ b/docs/cas-server-documentation/release_notes/RC5.md @@ -112,14 +112,14 @@ plugins or features, we recommend that you consider a better alternative or prep The following deprecated features and settings are now removed from the CAS codebase: -- Custom components used to provide or validate SAML2 tokens when CAS is configured to support [the WS Federation Protocol](../protocol/WS-Federation-Protocol.html). These components where only supplied to support OpenSAML v4 APIs and were deprecated in CAS `6.6.0`. +- Custom components used to provide or validate SAML2 tokens when CAS is configured to support [the WS Federation Protocol](../protocol/WS-Federation-Protocol.html). These components were only supplied to support OpenSAML v4 APIs and were deprecated in CAS `6.6.0`. - The *Legacy* strategy used to generate device record keys for trusted devices in a multifactor authentication flow. This strategy was deprecated in CAS `6.2.0` - The `requiredHandlers` setting assigned to a registered service definition. This setting was deprecated in CAS `6.2.0`. ### Google Cloud (GCP) Secret Manager [Google Cloud Secret Manager](../configuration/Configuration-Server-Management-SpringCloud-GCP-SecretManager.html) can -now be used as configuration source for CAS properties and settings. +now be used as a configuration source for CAS properties and settings. ### Attribute Definition Enhancements diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md new file mode 100644 index 000000000000..381d5efe4f8f --- /dev/null +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -0,0 +1,49 @@ +--- +layout: default +title: CAS - Release Notes +category: Planning +--- + +# 7.0.0-RC6 Release Notes + +We strongly recommend that you take advantage of the release candidates as they come out. Waiting for a `GA` release is only going to set +you up for unpleasant surprises. A `GA` is [a tag and nothing more](https://apereo.github.io/2017/03/08/the-myth-of-ga-rel/). Note +that CAS releases are *strictly* time-based releases; they are not scheduled or based on specific benchmarks, +statistics or completion of features. To gain confidence in a particular +release, it is strongly recommended that you start early by experimenting with release candidates and/or follow-up snapshots. + +## Apereo Membership + +If you benefit from Apereo CAS as free and open-source software, we invite you +to [join the Apereo Foundation](https://www.apereo.org/content/apereo-membership) +and financially support the project at a capacity that best suits your deployment. Note that all development activity is performed +*almost exclusively* on a voluntary basis with no expectations, commitments or strings attached. Having the financial means to better +sustain engineering activities will allow the developer community to allocate *dedicated and committed* time for long-term support, +maintenance and release planning, especially when it comes to addressing critical and security issues in a timely manner. + +## Get Involved + +- Start your CAS deployment today. Try out features and [share feedback](/cas/Mailing-Lists.html). +- Better yet, [contribute patches](/cas/developer/Contributor-Guidelines.html). +- Suggest and apply documentation improvements. + +## Resources + +- [Release Schedule](https://github.com/apereo/cas/milestones) +- [Release Policy](/cas/developer/Release-Policy.html) + +## System Requirements + +The JDK baseline requirement for this CAS release is and **MUST** be JDK `17`. All compatible distributions +such as Amazon Corretto, Zulu, Eclipse Temurin, etc should work and are implicitly supported. + +## New & Noteworthy + +The following items are new improvements and enhancements presented in this release. + + +## Other Stuff + + +## Library Upgrades + diff --git a/docs/cas-server-documentation/ticketing/Memcached-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/Memcached-Ticket-Registry.md index 4345747fd180..53e91d11e20c 100644 --- a/docs/cas-server-documentation/ticketing/Memcached-Ticket-Registry.md +++ b/docs/cas-server-documentation/ticketing/Memcached-Ticket-Registry.md @@ -10,8 +10,7 @@ category: Ticketing Memcached integration is enabled by including the following dependency in the WAR overlay: -{% include_cached casmodule.html group="org.apereo.cas" -module="cas-server-support-memcached-ticket-registry,cas-server-support-memcached-core" %} +{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-memcached-ticket-registry" %} This registry stores tickets in one or more [memcached](http://memcached.org/) instances. Memcached stores data in exactly one node among many in a distributed cache, thus avoiding the requirement to replicate diff --git a/gradle.properties b/gradle.properties index 1977de01c699..b16cd4e7c373 100644 --- a/gradle.properties +++ b/gradle.properties @@ -412,6 +412,7 @@ gsonVersion=2.10.1 # Google SDK / Spring Cloud ############################### googleCloudSdkVersion=4.1.2 +googleCloudMonitorVersion=3.13.0 ############################### # CouchDb Versions ############################### diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 7b14bde1a663..c3c290bb5372 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -13,6 +13,22 @@ ext.libraries = [ exclude(group: "org.bouncycastle", module: "bcprov-jdk15on") } ], + googlecloudpubsub : [ + dependencies.create("com.google.cloud:spring-cloud-gcp-starter-pubsub:$googleCloudSdkVersion") { + exclude(group: "org.slf4j", module: "slf4j-api") + exclude(group: "com.google.guava", module: "guava") + exclude(group: "commons-codec", module: "commons-codec") + exclude(group: "ch.qos.logback", module: "logback-core") + exclude(group: "ch.qos.logback", module: "logback-classic") + }, + dependencies.create("com.google.cloud:google-cloud-monitoring:$googleCloudMonitorVersion") { + exclude(group: "org.slf4j", module: "slf4j-api") + exclude(group: "com.google.guava", module: "guava") + exclude(group: "commons-codec", module: "commons-codec") + exclude(group: "ch.qos.logback", module: "logback-core") + exclude(group: "ch.qos.logback", module: "logback-classic") + } + ], googlecloudsecretsmanager : [ dependencies.create("com.google.cloud:spring-cloud-gcp-secretmanager:$googleCloudSdkVersion") { exclude(group: "org.slf4j", module: "slf4j-api") diff --git a/settings.gradle b/settings.gradle index 07ce1d669104..f9a3f203f4f0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -257,6 +257,7 @@ include "support:cas-server-support-gauth-jpa" include "support:cas-server-support-gauth-ldap" include "support:cas-server-support-gauth-mongo" include "support:cas-server-support-gauth-redis" +include "support:cas-server-support-gcp-ticket-registry" include "support:cas-server-support-generic" include "support:cas-server-support-generic-remote-webflow" include "support:cas-server-support-geolocation" diff --git a/style/checkstyle-rules.xml b/style/checkstyle-rules.xml index c618f8843d9e..1645e535d0ea 100644 --- a/style/checkstyle-rules.xml +++ b/style/checkstyle-rules.xml @@ -791,6 +791,13 @@ + + + + + + + diff --git a/support/cas-server-support-gcp-ticket-registry/build.gradle b/support/cas-server-support-gcp-ticket-registry/build.gradle new file mode 100644 index 000000000000..6d6dd8ee1e3d --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/build.gradle @@ -0,0 +1,41 @@ +description = "Apereo CAS GCP Ticket Registry" +ext { + publishMetadata = true + projectMetadata = [ + category: "Ticket Registries", + title: "Google Cloud Ticket Registry", + aliases: ["gcpregistry"] + ] +} +dependencies { + api project(":api:cas-server-core-api-util") + + implementation libraries.googlecloudpubsub + + implementation project(":core:cas-server-core-tickets") + implementation project(":core:cas-server-core-tickets-api") + implementation project(":core:cas-server-core-configuration-api") + implementation project(":core:cas-server-core-util-api") + + testImplementation project(":support:cas-server-support-person-directory") + + testImplementation project(":core:cas-server-core") + testImplementation project(":core:cas-server-core-services") + testImplementation project(":core:cas-server-core-util") + testImplementation project(":core:cas-server-core-cookie") + testImplementation project(":core:cas-server-core-web") + testImplementation project(":core:cas-server-core-logout-api") + testImplementation project(":core:cas-server-core-logout") + testImplementation project(":core:cas-server-core-configuration") + testImplementation project(":core:cas-server-core-authentication") + testImplementation project(":core:cas-server-core-services-authentication") + testImplementation project(":core:cas-server-core-authentication-api") + testImplementation project(":core:cas-server-core-notifications") + testImplementation project(":core:cas-server-core-authentication-attributes") + + testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") + testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") + testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") + testImplementation project(path: ":core:cas-server-core-tickets", configuration: "tests") + testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") +} diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java new file mode 100644 index 000000000000..2bb2363ca501 --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java @@ -0,0 +1,16 @@ +package org.apereo.cas.ticket.registry; + +import org.apereo.cas.ticket.TicketDefinition; + +import com.google.cloud.pubsub.v1.Subscriber; +import com.google.pubsub.v1.Subscription; +import com.google.pubsub.v1.Topic; + +/** + * This is {@link GoogleCloudPubSubMessageContext}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +public record GoogleCloudPubSubMessageContext(Topic topic, Subscription subscription, Subscriber subscriber) { +} diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-gcp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000000..126cbfdfbfc9 --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.apereo.cas.config.GoogleCloudTicketRegistryConfiguration diff --git a/support/cas-server-support-gcp-ticket-registry/src/test/resources/log4j2-test.xml b/support/cas-server-support-gcp-ticket-registry/src/test/resources/log4j2-test.xml new file mode 100644 index 000000000000..e94d8df5aa01 --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/test/resources/log4j2-test.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + From aee188e6fd8ec580d3a1e51e88d02468444946b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?CAS=20in=20the=20cloud=20LELEU=20J=C3=A9r=C3=B4me?= Date: Mon, 13 Mar 2023 16:59:08 +0100 Subject: [PATCH 003/266] Fix inconsistency in spec (#5613) --- .../installation/Logout-Single-Signout.md | 2 +- .../protocol/CAS-Protocol-Specification.md | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/cas-server-documentation/installation/Logout-Single-Signout.md b/docs/cas-server-documentation/installation/Logout-Single-Signout.md index f4fb4e8e2241..1bdc055a8b2c 100644 --- a/docs/cas-server-documentation/installation/Logout-Single-Signout.md +++ b/docs/cas-server-documentation/installation/Logout-Single-Signout.md @@ -70,7 +70,7 @@ A sample back channel SLO message: ID="[RANDOM ID]" Version="2.0" IssueInstant="[CURRENT DATE/TIME]"> - @NOT_USED@ + [PRINCIPAL IDENTIFIER] [SESSION IDENTIFIER] ``` diff --git a/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md b/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md index 15e78c6dfea1..ca38d1570bfe 100644 --- a/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md +++ b/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md @@ -1734,9 +1734,7 @@ following SAML Logout Request XML document: ```xml - - @NOT_USED@ - + [PRINCIPAL IDENTIFIER] [SESSION IDENTIFIER] ``` From 3fab2be138fc553fd44220a25e5852eac7300b84 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Mon, 13 Mar 2023 21:00:38 +0400 Subject: [PATCH 004/266] support GCP as a ticket registry impl --- .../registry/AbstractTicketRegistry.java | 11 +- .../release_notes/RC6.md | 12 +- docs/cas-server-documentation/sidebar.md | 1 + .../Configuring-Ticketing-Components.md | 1 + .../ticketing/GCP-PubSub-Ticket-Registry.md | 47 ++++++ gradle.properties | 16 +- ...oogleCloudTicketRegistryConfiguration.java | 155 ++++++++++++++++++ .../GoogleCloudPubSubMessageConverter.java | 46 ++++++ ...oudTicketRegistryMessageQueueConsumer.java | 54 ++++++ ...ogleCloudTicketRegistryQueuePublisher.java | 46 ++++++ .../GoogleCloudTicketRegistryTests.java | 152 +++++++++++++++++ 11 files changed, 525 insertions(+), 16 deletions(-) create mode 100644 docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md create mode 100644 support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/config/GoogleCloudTicketRegistryConfiguration.java create mode 100644 support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageConverter.java create mode 100644 support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java create mode 100644 support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java create mode 100644 support/cas-server-support-gcp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryTests.java diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java index 463d51f01574..ae1fc2511741 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java @@ -10,7 +10,6 @@ import org.apereo.cas.ticket.Ticket; import org.apereo.cas.ticket.TicketCatalog; import org.apereo.cas.ticket.TicketGrantingTicket; -import org.apereo.cas.ticket.TicketGrantingTicketAwareTicket; import org.apereo.cas.ticket.proxy.ProxyGrantingTicket; import org.apereo.cas.ticket.serialization.TicketSerializationManager; import org.apereo.cas.util.CollectionUtils; @@ -189,7 +188,7 @@ public long countSessionsFor(final String principalId) { @Override public Stream getSessionsWithAttributes(final Map> queryAttributes) { return getTickets(ticket -> { - if (ticket instanceof TicketGrantingTicketAwareTicket ticketGrantingTicket && !ticket.isExpired() + if (ticket instanceof TicketGrantingTicket ticketGrantingTicket && !ticket.isExpired() && ticketGrantingTicket.getAuthentication() != null) { val attributes = collectAndDigestTicketAttributes(ticketGrantingTicket); @@ -197,9 +196,9 @@ public Stream getSessionsWithAttributes(final Map { val attributeValue = value.toString(); return queryEntry.getValue() @@ -228,7 +227,7 @@ public Stream getSessionsWithAttributes(final Map tickets) { return deleteTickets(tickets.stream()); } - + protected int deleteTickets(final Stream tickets) { return tickets.mapToInt(Unchecked.toIntFunction(this::deleteTicket)).sum(); } @@ -322,7 +321,7 @@ protected Ticket decodeTicket(final Ticket ticketToProcess) { protected Collection decodeTickets(final Collection items) { return decodeTickets(items.stream()).collect(Collectors.toSet()); } - + protected Stream decodeTickets(final Stream items) { if (!isCipherExecutorEnabled()) { LOGGER.trace(MESSAGE); diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index 381d5efe4f8f..cb5ccb928cd9 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -41,9 +41,17 @@ such as Amazon Corretto, Zulu, Eclipse Temurin, etc should work and are implicit The following items are new improvements and enhancements presented in this release. +### Google Cloud Pub/Sub Ticket Registry + +A new ticket registry implementation backed by [Google Cloud's PubSub](../ticketing/GCP-PubSub-Ticket-Registry.html) is now available. ## Other Stuff - + + ## Library Upgrades - + +- Ldaptive +- Twillio +- Amazon SDK +- Spring Boot diff --git a/docs/cas-server-documentation/sidebar.md b/docs/cas-server-documentation/sidebar.md index b0d8f182ad10..b23f6647ccca 100644 --- a/docs/cas-server-documentation/sidebar.md +++ b/docs/cas-server-documentation/sidebar.md @@ -379,6 +379,7 @@ layout: null * [Storage](#ticketingstorage) * [Default](/cas/{{ version }}/ticketing/Default-Ticket-Registry.html) * [AMQP](/cas/{{ version }}/ticketing/Messaging-AMQP-Ticket-Registry.html) + * [Google Cloud PubSub](/cas/{{ version }}/ticketing/GCP-PubSub-Ticket-Registry.html) * [Hazelcast](#hazelcastticketregistry) * [Overview](/cas/{{ version }}/ticketing/Hazelcast-Ticket-Registry.html) * [WAN Replication](/cas/{{ version }}/ticketing/Hazelcast-Ticket-Registry-WAN-Replication.html) diff --git a/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md b/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md index 3eaef3f96545..38028ef73cab 100644 --- a/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md +++ b/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md @@ -44,6 +44,7 @@ deployments. Components for the following caching technologies are provided: ### Message-based Ticket Registries * [AMQP](Messaging-AMQP-Ticket-Registry.html) +* [Google Cloud PubSub](GCP-PubSub-Ticket-Registry.html) ### RDBMS Ticket Registries diff --git a/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md new file mode 100644 index 000000000000..2ae5a7519f2e --- /dev/null +++ b/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md @@ -0,0 +1,47 @@ +--- +layout: default +title: CAS - GCP PubSub Ticket Registry +category: Ticketing +--- + +{% include variables.html %} + +# Google Cloud Pub/Sub Ticket Registry + +This registry is very much an extension of the [default ticket registry](Default-Ticket-Registry.html). +The difference is that ticket operations applied to the registry are broadcasted using [Google Cloud's PubSub](https://cloud.google.com/pubsub). + +Each node keeps copies of ticket state on its own and only instructs others to keep their copy accurate by broadcasting messages and data associated with each. +Each message and ticket registry instance running inside a CAS node in the cluster is tagged with a unique +identifier in order to avoid endless looping behavior and recursive needless inbound operations. + +
:information_source: Message Ordering +

This registry implementation requires you to enable message ordering via CAS settings.

+
+ +Support is enabled by including the following dependency in the overlay: + +{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-gcp-ticket-registry" %} + +## CAS Configuration + +{% include_cached casproperties.html properties="cas.ticket.registry.in-memory" thirdPartyStartsWith="spring.cloud.gcp.pubsub" %} + +## Actuator Endpoints + +The following endpoints are provided by CAS: + +{% include_cached actuators.html endpoints="health" healthIndicators="pubsub,pubsub-subscriber" %} + +## Troubleshooting + +To enable additional logging, configure the log4j configuration file to add the following levels: + +```xml +... + + + + +... +``` diff --git a/gradle.properties b/gradle.properties index b16cd4e7c373..8a92d0bada9d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,7 +33,7 @@ targetCompatibility=17 lombokVersion=1.18.26 aspectjVersion=1.9.19 errorProneVersion=2.18.0 -groovyVersion=4.0.9 +groovyVersion=4.0.10 caffeineVersion=3.1.5 joolVersion=0.9.15 javassistVersion=3.29.0-GA @@ -57,7 +57,7 @@ awaitilityVersion=4.2.0 ##################################################### # Gradle Plugins & Build Utilities ###################################################### -checkstyleVersion=10.8.0 +checkstyleVersion=10.8.1 gradleRetryVersion=1.5.2 gradleGitVersion=2.4.1 gradleLombokVersion=5.0.0 @@ -102,7 +102,7 @@ fluentdLog4jVersion=1.0.0 ############################### springBootVersion=3.0.4 springVersion=6.0.6 -springBootAdminVersion=3.0.0 +springBootAdminVersion=3.0.1 ############################### # Spring Retry versions ############################### @@ -184,7 +184,7 @@ postgresqlVersion=42.5.4 yugabytedbVersion=42.3.4 mariaDbVersion=3.1.2 jtdsVersion=1.3.1 -mssqlServerVersion=11.2.1.jre17 +mssqlServerVersion=11.2.3.jre17 oracleJdbcVersion=19.3.0.0 mongoDriverVersion=4.9.0 ############################### @@ -319,8 +319,8 @@ firebaseAdminVersion=9.1.1 ############################### # LDAP versions ############################### -ldaptiveVersion=2.1.1 -unboundidVersion=6.0.7 +ldaptiveVersion=2.1.2 +unboundidVersion=6.0.8 nettyVersion=4.1.89.Final ############################### # SPNEGO versions @@ -359,7 +359,7 @@ kryoSerializersVersion=0.45 # SMS versions ############################### nexmoVersion=5.6.0 -twilioVersion=9.2.4 +twilioVersion=9.2.5 textMagicVersion=2.0.2456 ############################### # JWT versions @@ -388,7 +388,7 @@ jdomVersion=2.0.6.1 ############################### # Grouper versions ############################### -grouperVersion=4.0.0 +grouperVersion=4.0.3 ############################### # Email versions ############################### diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/config/GoogleCloudTicketRegistryConfiguration.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/config/GoogleCloudTicketRegistryConfiguration.java new file mode 100644 index 000000000000..e2c2f512b012 --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/config/GoogleCloudTicketRegistryConfiguration.java @@ -0,0 +1,155 @@ +package org.apereo.cas.config; + +import org.apereo.cas.configuration.CasConfigurationProperties; +import org.apereo.cas.configuration.features.CasFeatureModule; +import org.apereo.cas.ticket.registry.GoogleCloudPubSubMessageContext; +import org.apereo.cas.ticket.registry.GoogleCloudPubSubMessageConverter; +import org.apereo.cas.ticket.registry.GoogleCloudTicketRegistryMessageQueueConsumer; +import org.apereo.cas.ticket.registry.GoogleCloudTicketRegistryQueuePublisher; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessageReceiver; +import org.apereo.cas.util.PublisherIdentifier; +import org.apereo.cas.util.crypto.CipherExecutor; +import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; + +import com.google.cloud.pubsub.v1.Subscriber; +import com.google.cloud.spring.core.GcpProjectIdProvider; +import com.google.cloud.spring.pubsub.PubSubAdmin; +import com.google.cloud.spring.pubsub.core.PubSubTemplate; +import com.google.cloud.spring.pubsub.support.PubSubTopicUtils; +import com.google.cloud.spring.pubsub.support.converter.PubSubMessageConverter; +import com.google.pubsub.v1.DeadLetterPolicy; +import com.google.pubsub.v1.Subscription; +import com.google.pubsub.v1.Topic; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +/** + * This is {@link GoogleCloudTicketRegistryConfiguration}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@EnableConfigurationProperties(CasConfigurationProperties.class) +@EnableTransactionManagement(proxyTargetClass = false) +@EnableScheduling +@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.TicketRegistry, module = "gcp") +@AutoConfiguration +@Slf4j +@Lazy(false) +public class GoogleCloudTicketRegistryConfiguration { + + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @ConditionalOnMissingBean(name = "pubSubMessageConverter") + public PubSubMessageConverter pubSubMessageConverter( + @Qualifier("defaultTicketRegistryCipherExecutor") + final CipherExecutor defaultTicketRegistryCipherExecutor) { + return new GoogleCloudPubSubMessageConverter(defaultTicketRegistryCipherExecutor); + } + + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + public QueueableTicketRegistryMessagePublisher messageQueueTicketRegistryPublisher( + @Qualifier("pubSubMessageConverter") + final PubSubMessageConverter pubSubMessageConverter, + @Qualifier("messageQueueTicketRegistryIdentifier") + final PublisherIdentifier messageQueueTicketRegistryIdentifier, + final PubSubTemplate pubSubTemplate) { + LOGGER.debug("Configuring Google Cloud ticket registry with identifier [{}]", messageQueueTicketRegistryIdentifier); + pubSubTemplate.setMessageConverter(pubSubMessageConverter); + return new GoogleCloudTicketRegistryQueuePublisher(pubSubTemplate); + } + + @Bean + @ConditionalOnMissingBean(name = "googleCloudPubSubTopics") + public Map googleCloudPubSubTopics( + final GcpProjectIdProvider gcpProjectIdProvider, + @Qualifier("pubSubMessageConverter") + final PubSubMessageConverter pubSubMessageConverter, + @Qualifier("messageQueueTicketRegistryReceiver") + final QueueableTicketRegistryMessageReceiver messageQueueTicketRegistryReceiver, + final PubSubTemplate pubSubTemplate, + final PubSubAdmin pubSubAdmin) { + + val googleCloudTopics = new LinkedHashMap(); + + LOGGER.info("Preparing Google Cloud Pub/Sub topics and subscriptions..."); + val allTopics = pubSubAdmin.listTopics(); + val allSubcriptions = pubSubAdmin.listSubscriptions(); + + val topicName = GoogleCloudTicketRegistryQueuePublisher.QUEUE_TOPIC; + val subscriptionName = topicName.concat("Subscription"); + + if (findTopicByName(allTopics, GoogleCloudTicketRegistryQueuePublisher.DEAD_LETTER_TOPIC).isEmpty()) { + pubSubAdmin.createTopic(GoogleCloudTicketRegistryQueuePublisher.DEAD_LETTER_TOPIC); + } + val topic = findTopicByName(allTopics, topicName) + .orElseGet(() -> Objects.requireNonNull(pubSubAdmin.createTopic(topicName))); + val subscription = getOrCreateSubscription(pubSubAdmin, gcpProjectIdProvider, + allSubcriptions, subscriptionName, topic); + LOGGER.debug("Created subscription [{}] for topic [{}]", subscription.getName(), topic.getName()); + val subscriber = subscribeToTopic(messageQueueTicketRegistryReceiver, pubSubTemplate, topic, subscription, pubSubMessageConverter); + val context = new GoogleCloudPubSubMessageContext(topic, subscription, subscriber); + googleCloudTopics.put(context.topic().getName(), context); + return googleCloudTopics; + } + + private static Optional findTopicByName(final List allTopics, final String topicName) { + return allTopics + .stream() + .filter(topic -> topic.getName().contains(topicName)) + .findFirst(); + } + + private static Subscriber subscribeToTopic(final QueueableTicketRegistryMessageReceiver messageQueueTicketRegistryReceiver, + final PubSubTemplate pubSubTemplate, + final Topic topic, + final Subscription subscription, + final PubSubMessageConverter messageQueueTicketRegistryConverter) { + val messageConsumer = new GoogleCloudTicketRegistryMessageQueueConsumer(topic, subscription, + messageQueueTicketRegistryReceiver, messageQueueTicketRegistryConverter); + return pubSubTemplate.subscribe(subscription.getName(), messageConsumer); + } + + private static Subscription getOrCreateSubscription(final PubSubAdmin pubSubAdmin, + final GcpProjectIdProvider gcpProjectIdProvider, + final List allSubcriptions, + final String subscriptionName, + final Topic topic) { + return allSubcriptions + .stream() + .filter(sub -> sub.getName().contains(subscriptionName)) + .findFirst() + .orElseGet(() -> { + val deadLetterTopic = PubSubTopicUtils + .toTopicName(GoogleCloudTicketRegistryQueuePublisher.DEAD_LETTER_TOPIC, gcpProjectIdProvider.getProjectId()) + .toString(); + val deadLetterPolicy = DeadLetterPolicy + .newBuilder() + .setDeadLetterTopic(deadLetterTopic) + .setMaxDeliveryAttempts(5) + .build(); + return pubSubAdmin.createSubscription(Subscription.newBuilder() + .setName(subscriptionName) + .setTopic(topic.getName()) + .setDeadLetterPolicy(deadLetterPolicy)); + }); + } +} diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageConverter.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageConverter.java new file mode 100644 index 000000000000..eef764d46748 --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageConverter.java @@ -0,0 +1,46 @@ +package org.apereo.cas.ticket.registry; + +import org.apereo.cas.util.crypto.CipherExecutor; +import org.apereo.cas.util.function.FunctionUtils; +import org.apereo.cas.util.serialization.JacksonObjectMapperFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.cloud.spring.pubsub.support.converter.SimplePubSubMessageConverter; +import com.google.pubsub.v1.PubsubMessage; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * This is {@link GoogleCloudPubSubMessageConverter}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@RequiredArgsConstructor +public class GoogleCloudPubSubMessageConverter extends SimplePubSubMessageConverter { + private static final ObjectMapper MAPPER = JacksonObjectMapperFactory.builder() + .defaultTypingEnabled(true).build().toObjectMapper(); + + private final CipherExecutor cipherExecutor; + + @Override + public PubsubMessage toPubSubMessage(final Object payload, final Map headers) { + return FunctionUtils.doUnchecked(() -> { + val serialized = MAPPER.writeValueAsString(payload).getBytes(StandardCharsets.UTF_8); + val convertedPayload = cipherExecutor.encode(serialized); + return super.toPubSubMessage(convertedPayload, headers); + }); + } + + @Override + public T fromPubSubMessage(final PubsubMessage message, final Class payloadType) { + return FunctionUtils.doUnchecked(() -> { + val payload = new String(cipherExecutor.decode(message.getData().toByteArray()), StandardCharsets.UTF_8); + return MAPPER.readValue(payload, payloadType); + }); + + } +} diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java new file mode 100644 index 000000000000..e9d6b5034b1e --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java @@ -0,0 +1,54 @@ +package org.apereo.cas.ticket.registry; + +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessageReceiver; +import org.apereo.cas.util.LoggingUtils; +import org.apereo.cas.util.function.FunctionUtils; + +import com.google.cloud.spring.pubsub.support.BasicAcknowledgeablePubsubMessage; +import com.google.cloud.spring.pubsub.support.converter.PubSubMessageConverter; +import com.google.pubsub.v1.Subscription; +import com.google.pubsub.v1.Topic; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.jooq.lambda.fi.util.function.CheckedFunction; + +import java.util.Objects; +import java.util.function.Consumer; + +/** + * This is {@link GoogleCloudTicketRegistryMessageQueueConsumer}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@Slf4j +@RequiredArgsConstructor +@Getter +public class GoogleCloudTicketRegistryMessageQueueConsumer implements Consumer { + private final Topic topic; + + private final Subscription subscription; + + private final QueueableTicketRegistryMessageReceiver messageQueueTicketRegistryReceiver; + + private final PubSubMessageConverter pubSubMessageConverter; + + @Override + @SuppressWarnings("FutureReturnValueIgnored") + public void accept(final BasicAcknowledgeablePubsubMessage message) { + FunctionUtils.doAndHandle(o -> { + val subName = message.getProjectSubscriptionName().getSubscription(); + LOGGER.debug("Message received from {} subscription: {}", subName, + message.getPubsubMessage().getData().toStringUtf8()); + val command = pubSubMessageConverter.fromPubSubMessage(message.getPubsubMessage(), BaseMessageQueueCommand.class); + messageQueueTicketRegistryReceiver.receive(command); + Objects.requireNonNull(message.ack()); + }, (CheckedFunction) e -> { + LoggingUtils.error(LOGGER, e); + return message.nack(); + }).accept(message); + } +} diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java new file mode 100644 index 000000000000..54435b0613a5 --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java @@ -0,0 +1,46 @@ +package org.apereo.cas.ticket.registry; + +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessagePublisher; +import org.apereo.cas.util.function.FunctionUtils; + +import com.google.cloud.spring.pubsub.core.PubSubTemplate; +import com.google.cloud.spring.pubsub.support.GcpPubSubHeaders; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * This is {@link GoogleCloudTicketRegistryQueuePublisher}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@Slf4j +@RequiredArgsConstructor +@Getter +public class GoogleCloudTicketRegistryQueuePublisher implements QueueableTicketRegistryMessagePublisher { + /** + * Topic destination name. + */ + public static final String QUEUE_TOPIC = "CasTicketRegistryTopic"; + public static final String DEAD_LETTER_TOPIC = QUEUE_TOPIC + "DeadLetter"; + + private final PubSubTemplate pubSubTemplate; + + @Override + public void publishMessageToQueue(final BaseMessageQueueCommand cmd) { + FunctionUtils.doAndHandle(__ -> { + LOGGER.debug("[{}] is publishing message [{}]", cmd.getId().getId(), cmd); + val headers = Collections.singletonMap(GcpPubSubHeaders.ORDERING_KEY, cmd.getId().getId()); + final CompletableFuture publish = pubSubTemplate.publish(QUEUE_TOPIC, cmd, headers); + val publishedMessage = publish.get(); + LOGGER.trace("Sent message [{}] from ticket registry id [{}]", publishedMessage, cmd.getId()); + }); + } +} diff --git a/support/cas-server-support-gcp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryTests.java b/support/cas-server-support-gcp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryTests.java new file mode 100644 index 000000000000..9e2992292ceb --- /dev/null +++ b/support/cas-server-support-gcp-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryTests.java @@ -0,0 +1,152 @@ +package org.apereo.cas.ticket.registry; + +import org.apereo.cas.authentication.CoreAuthenticationTestUtils; +import org.apereo.cas.config.GoogleCloudTicketRegistryConfiguration; +import org.apereo.cas.ticket.TicketGrantingTicketImpl; +import org.apereo.cas.ticket.expiration.NeverExpiresExpirationPolicy; +import org.apereo.cas.ticket.registry.pubsub.commands.AddTicketMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.commands.BaseMessageQueueCommand; +import org.apereo.cas.ticket.registry.pubsub.queue.QueueableTicketRegistryMessageReceiver; +import org.apereo.cas.util.PublisherIdentifier; + +import com.google.cloud.pubsub.v1.SubscriptionAdminClient; +import com.google.cloud.pubsub.v1.TopicAdminClient; +import com.google.cloud.spring.core.GcpProjectIdProvider; +import com.google.cloud.spring.pubsub.PubSubAdmin; +import com.google.cloud.spring.pubsub.core.PubSubTemplate; +import com.google.cloud.spring.pubsub.core.publisher.PubSubPublisherTemplate; +import com.google.cloud.spring.pubsub.core.subscriber.PubSubSubscriberTemplate; +import com.google.cloud.spring.pubsub.support.BasicAcknowledgeablePubsubMessage; +import com.google.cloud.spring.pubsub.support.converter.PubSubMessageConverter; +import com.google.pubsub.v1.ProjectName; +import com.google.pubsub.v1.ProjectSubscriptionName; +import com.google.pubsub.v1.PubsubMessage; +import com.google.pubsub.v1.Subscription; +import com.google.pubsub.v1.Topic; +import com.google.pubsub.v1.TopicName; +import lombok.Getter; +import lombok.val; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * This is {@link GoogleCloudTicketRegistryTests}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@Tag("Tickets") +@Import({ + GoogleCloudTicketRegistryTests.GoogleCloudTestConfiguration.class, + GoogleCloudTicketRegistryConfiguration.class +}) +@Getter +public class GoogleCloudTicketRegistryTests extends BaseTicketRegistryTests { + @Autowired + @Qualifier(TicketRegistry.BEAN_NAME) + private TicketRegistry newTicketRegistry; + + @Autowired + @Qualifier("pubSubMessageConverter") + private PubSubMessageConverter pubSubMessageConverter; + + @Autowired + @Qualifier("messageQueueTicketRegistryReceiver") + private QueueableTicketRegistryMessageReceiver messageQueueTicketRegistryReceiver; + + @RepeatedTest(1) + @Tag("DisableTicketRegistryTestWithEncryption") + public void verifyConverter() { + val cmd = new AddTicketMessageQueueCommand(new PublisherIdentifier(), + new TicketGrantingTicketImpl(UUID.randomUUID().toString(), + CoreAuthenticationTestUtils.getAuthentication(), NeverExpiresExpirationPolicy.INSTANCE)); + val message = pubSubMessageConverter.toPubSubMessage(cmd, Map.of()); + assertNotNull(message); + val foundCmd = pubSubMessageConverter.fromPubSubMessage(message, BaseMessageQueueCommand.class); + assertNotNull(foundCmd); + } + + @RepeatedTest(1) + @Tag("DisableTicketRegistryTestWithEncryption") + public void verifyTicketConsumer() throws Exception { + val objectToSend = new AddTicketMessageQueueCommand(new PublisherIdentifier(), + new TicketGrantingTicketImpl(UUID.randomUUID().toString(), + CoreAuthenticationTestUtils.getAuthentication(), NeverExpiresExpirationPolicy.INSTANCE)); + val originalMessage = pubSubMessageConverter.toPubSubMessage(objectToSend, Map.of()); + + val topic = Topic.newBuilder().setName(UUID.randomUUID().toString()).build(); + val subscription = Subscription.newBuilder().setName(UUID.randomUUID().toString()).build(); + val cmd = new GoogleCloudTicketRegistryMessageQueueConsumer(topic, subscription, + messageQueueTicketRegistryReceiver, pubSubMessageConverter); + val message = mock(BasicAcknowledgeablePubsubMessage.class); + when(message.getProjectSubscriptionName()) + .thenReturn(ProjectSubscriptionName.of("project", "subscription")); + when(message.getPubsubMessage()).thenReturn(originalMessage); + + val apiFuture = mock(CompletableFuture.class); + when(apiFuture.get()).thenReturn(Boolean.TRUE.toString()); + when(message.ack()).thenReturn(apiFuture); + when(message.nack()).thenReturn(apiFuture); + + assertDoesNotThrow(() -> cmd.accept(message)); + + when(message.getProjectSubscriptionName()).thenReturn(null); + assertDoesNotThrow(() -> cmd.accept(message)); + } + + @TestConfiguration(value = "GoogleCloudTestConfiguration", proxyBeanMethods = false) + public static class GoogleCloudTestConfiguration { + @Bean + public GcpProjectIdProvider gcpProjectIdProvider() { + return () -> UUID.randomUUID().toString(); + } + + @Bean + public PubSubAdmin pubSubAdmin(final GcpProjectIdProvider gcpProjectIdProvider) { + val topicAdminClient = mock(TopicAdminClient.class); + val listResponse = mock(TopicAdminClient.ListTopicsPagedResponse.class); + when(listResponse.iterateAll()).thenReturn(List.of()); + + val topic = Topic.newBuilder().setName(GoogleCloudTicketRegistryQueuePublisher.QUEUE_TOPIC).build(); + when(topicAdminClient.createTopic(anyString())).thenReturn(topic); + when(topicAdminClient.createTopic(any(TopicName.class))).thenReturn(topic); + + when(topicAdminClient.listTopics(any(ProjectName.class))).thenReturn(listResponse); + + val subscriptionAdminClient = mock(SubscriptionAdminClient.class); + val listSubsResponse = mock(SubscriptionAdminClient.ListSubscriptionsPagedResponse.class); + when(listSubsResponse.iterateAll()).thenReturn(List.of()); + when(subscriptionAdminClient.listSubscriptions(any(ProjectName.class))).thenReturn(listSubsResponse); + val subscription = Subscription.newBuilder().setName("MySubscription").build(); + when(subscriptionAdminClient.createSubscription(any(Subscription.class))).thenReturn(subscription); + + return new PubSubAdmin(gcpProjectIdProvider, topicAdminClient, subscriptionAdminClient); + } + + @Bean + public PubSubTemplate pubSubTemplate() throws Exception { + val apiFuture = mock(CompletableFuture.class); + when(apiFuture.get()).thenReturn(Boolean.TRUE.toString()); + val pubSubPublisherTemplate = mock(PubSubPublisherTemplate.class); + when(pubSubPublisherTemplate.publish(anyString(), any(PubsubMessage.class))).thenReturn(apiFuture); + when(pubSubPublisherTemplate.publish(anyString(), any(), anyMap())).thenReturn(apiFuture); + + val pubSubSubscriberTemplate = mock(PubSubSubscriberTemplate.class); + + return new PubSubTemplate(pubSubPublisherTemplate, pubSubSubscriberTemplate); + } + } +} From 82cdab1c35ce24c6af0e8c89251b3c9f2370e991 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Tue, 14 Mar 2023 11:06:58 +0400 Subject: [PATCH 005/266] doc updates --- .../ticketing/GCP-PubSub-Ticket-Registry.md | 8 ++++++++ support/cas-server-support-gauth/build.gradle | 2 +- .../registry/GoogleCloudPubSubMessageContext.java | 2 -- ...GoogleCloudTicketRegistryMessageQueueConsumer.java | 2 +- .../GoogleCloudTicketRegistryQueuePublisher.java | 11 ++++++++--- .../build.gradle | 3 ++- support/cas-server-support-saml-idp/build.gradle | 2 +- support/cas-server-support-sentry/build.gradle | 3 ++- 8 files changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md index 2ae5a7519f2e..19c74e4eae9c 100644 --- a/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md +++ b/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md @@ -23,6 +23,10 @@ Support is enabled by including the following dependency in the overlay: {% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-gcp-ticket-registry" %} +Integration support is backed by the [Spring Cloud GCP project](https://cloud.google.com/java/docs/spring). +Their [reference documentation](https://googlecloudplatform.github.io/spring-cloud-gcp/reference/html/index.html) +provides detailed information on how to integrate Google Cloud APIs with CAS. + ## CAS Configuration {% include_cached casproperties.html properties="cas.ticket.registry.in-memory" thirdPartyStartsWith="spring.cloud.gcp.pubsub" %} @@ -33,6 +37,10 @@ The following endpoints are provided by CAS: {% include_cached actuators.html endpoints="health" healthIndicators="pubsub,pubsub-subscriber" %} +
:information_source: Message Ordering +

To successfully use the Spring Cloud GCP actuator endpoints, you will also need to enable the Cloud Monitoring API.

+
+ ## Troubleshooting To enable additional logging, configure the log4j configuration file to add the following levels: diff --git a/support/cas-server-support-gauth/build.gradle b/support/cas-server-support-gauth/build.gradle index 675b2d0bc6ce..ccfb53b38820 100644 --- a/support/cas-server-support-gauth/build.gradle +++ b/support/cas-server-support-gauth/build.gradle @@ -4,7 +4,7 @@ ext { projectMetadata = [ category: "Google Authenticator Multifactor Authentication", title: "Google Authenticator Support", - aliases: ["gauth"] + aliases: ["gauth", "googlemfa"] ] } dependencies { diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java index 2bb2363ca501..c4dad7990a80 100644 --- a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudPubSubMessageContext.java @@ -1,7 +1,5 @@ package org.apereo.cas.ticket.registry; -import org.apereo.cas.ticket.TicketDefinition; - import com.google.cloud.pubsub.v1.Subscriber; import com.google.pubsub.v1.Subscription; import com.google.pubsub.v1.Topic; diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java index e9d6b5034b1e..340407a99d49 100644 --- a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryMessageQueueConsumer.java @@ -41,7 +41,7 @@ public class GoogleCloudTicketRegistryMessageQueueConsumer implements Consumer { val subName = message.getProjectSubscriptionName().getSubscription(); - LOGGER.debug("Message received from {} subscription: {}", subName, + LOGGER.debug("Message received from [{}] subscription: [{}]", subName, message.getPubsubMessage().getData().toStringUtf8()); val command = pubSubMessageConverter.fromPubSubMessage(message.getPubsubMessage(), BaseMessageQueueCommand.class); messageQueueTicketRegistryReceiver.receive(command); diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java index 54435b0613a5..4a7491cc5a75 100644 --- a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java @@ -12,7 +12,7 @@ import lombok.val; import java.util.Collections; -import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; /** @@ -29,6 +29,10 @@ public class GoogleCloudTicketRegistryQueuePublisher implements QueueableTicketR * Topic destination name. */ public static final String QUEUE_TOPIC = "CasTicketRegistryTopic"; + + /** + * The dead-letter topic name. + */ public static final String DEAD_LETTER_TOPIC = QUEUE_TOPIC + "DeadLetter"; private final PubSubTemplate pubSubTemplate; @@ -38,8 +42,9 @@ public void publishMessageToQueue(final BaseMessageQueueCommand cmd) { FunctionUtils.doAndHandle(__ -> { LOGGER.debug("[{}] is publishing message [{}]", cmd.getId().getId(), cmd); val headers = Collections.singletonMap(GcpPubSubHeaders.ORDERING_KEY, cmd.getId().getId()); - final CompletableFuture publish = pubSubTemplate.publish(QUEUE_TOPIC, cmd, headers); - val publishedMessage = publish.get(); + val future = pubSubTemplate.publish(QUEUE_TOPIC, cmd, headers); + Objects.requireNonNull(future); + val publishedMessage = future.get(); LOGGER.trace("Sent message [{}] from ticket registry id [{}]", publishedMessage, cmd.getId()); }); } diff --git a/support/cas-server-support-saml-idp-discovery/build.gradle b/support/cas-server-support-saml-idp-discovery/build.gradle index b2bd30e4dc2f..251298911048 100644 --- a/support/cas-server-support-saml-idp-discovery/build.gradle +++ b/support/cas-server-support-saml-idp-discovery/build.gradle @@ -3,7 +3,8 @@ ext { publishMetadata = true projectMetadata = [ category: "SAML2 Protocol", - title: "SAML2 Identity Provider Discovery" + title: "SAML2 Identity Provider Discovery", + aliases: ["saml2discovery"] ] } dependencies { diff --git a/support/cas-server-support-saml-idp/build.gradle b/support/cas-server-support-saml-idp/build.gradle index 2dc84a3bba37..693f4e0a5c30 100644 --- a/support/cas-server-support-saml-idp/build.gradle +++ b/support/cas-server-support-saml-idp/build.gradle @@ -4,7 +4,7 @@ ext { publishMetadata = true projectMetadata = [ category: "SAML2 Protocol", - title: "SAML2 Identity Provider Discovery", + title: "SAML2 Identity Provider", aliases: ["saml2"] ] } diff --git a/support/cas-server-support-sentry/build.gradle b/support/cas-server-support-sentry/build.gradle index 61b14898e82e..97498c52ee44 100644 --- a/support/cas-server-support-sentry/build.gradle +++ b/support/cas-server-support-sentry/build.gradle @@ -3,7 +3,8 @@ ext { publishMetadata = true projectMetadata = [ category: "Monitoring", - title: "Apereo CAS Sentry Monitoring" + title: "Apereo CAS Sentry Monitoring", + aliases: ["sentry"] ] } dependencies { From f1008397873ebf3de0f09b6e32a5bc49fc906f8e Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Tue, 14 Mar 2023 19:45:43 +0400 Subject: [PATCH 006/266] minor build fixes --- .../ticketing/GCP-PubSub-Ticket-Registry.md | 2 +- .../registry/GoogleCloudTicketRegistryQueuePublisher.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md index 19c74e4eae9c..bca27076bcbe 100644 --- a/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md +++ b/docs/cas-server-documentation/ticketing/GCP-PubSub-Ticket-Registry.md @@ -37,7 +37,7 @@ The following endpoints are provided by CAS: {% include_cached actuators.html endpoints="health" healthIndicators="pubsub,pubsub-subscriber" %} -
:information_source: Message Ordering +
:information_source: Cloud Monitoring

To successfully use the Spring Cloud GCP actuator endpoints, you will also need to enable the Cloud Monitoring API.

diff --git a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java index 4a7491cc5a75..c85b1d2520e0 100644 --- a/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java +++ b/support/cas-server-support-gcp-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/GoogleCloudTicketRegistryQueuePublisher.java @@ -13,7 +13,6 @@ import java.util.Collections; import java.util.Objects; -import java.util.concurrent.CompletableFuture; /** * This is {@link GoogleCloudTicketRegistryQueuePublisher}. From fcc3a6c96a2bd28e90d84602f622fafc58cb309d Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Tue, 14 Mar 2023 22:22:44 +0400 Subject: [PATCH 007/266] Update Attribute-Resolution-Groovy.md --- .../integration/Attribute-Resolution-Groovy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cas-server-documentation/integration/Attribute-Resolution-Groovy.md b/docs/cas-server-documentation/integration/Attribute-Resolution-Groovy.md index 0e8bf3d04875..189a9038d382 100644 --- a/docs/cas-server-documentation/integration/Attribute-Resolution-Groovy.md +++ b/docs/cas-server-documentation/integration/Attribute-Resolution-Groovy.md @@ -24,10 +24,10 @@ def run(final Object... args) { def properties = args[3] def appContext = args[4] - logger.debug("[{}]: The received uid is [{}]", this.class.simpleName, uid) + logger.debug("[{}]: The received uid is [{}]", this.class.simpleName, username) // All attribute values must be defined as a collection wrapped in [] - return [username:[uid], likes:["cheese", "food"], id:[1234,2,3,4,5], another:["attribute"] ] + return [username:[username], likes:["cheese", "food"], id:[1234,2,3,4,5], another:["attribute"] ] } ``` From 6c23bd53e4e7cecf78b8ec877401e22f875ab11a Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 15 Mar 2023 11:45:05 +0400 Subject: [PATCH 008/266] remove possibility of stackoverflow when username provider defined an attribute --- ...teredServiceUsernameAttributeProvider.java | 9 +-- ...isteredServiceUsernameProviderContext.java | 32 ++++++++ .../DefaultAuthenticationBuilder.java | 19 +++-- ...gisteredServiceAttributeReleasePolicy.java | 60 ++++----------- ...redServiceAttributeReleasePolicyTests.java | 5 +- ...urnAllowedAttributeReleasePolicyTests.java | 6 +- ...teredServiceUsernameAttributeProvider.java | 6 +- ...teredServiceUsernameAttributeProvider.java | 28 +++---- ...aultRegisteredServiceUsernameProvider.java | 9 +-- ...oovyRegisteredServiceUsernameProvider.java | 18 ++--- ...buteRegisteredServiceUsernameProvider.java | 77 +++++++++---------- ...ServiceUsernameAttributeProviderTests.java | 33 +++++--- ...egisteredServiceUsernameProviderTests.java | 45 ++++++++--- ...egisteredServiceUsernameProviderTests.java | 29 ++++--- ...egisteredServiceUsernameProviderTests.java | 60 +++++++++++---- .../cas/util/function/FunctionUtils.java | 17 ++++ .../services/JsonServiceRegistryTests.java | 31 ++++++++ .../resources/UsernameAttrRelease-100.json | 40 ++++++++++ ...th20ClientIdClientSecretAuthenticator.java | 9 ++- .../OAuth20UsernamePasswordAuthenticator.java | 10 ++- ...teredServiceUsernameAttributeProvider.java | 17 ++-- ...ServiceUsernameAttributeProviderTests.java | 31 ++++++-- .../GoogleAccountsServiceResponseBuilder.java | 10 ++- ...stractSamlIdPProfileHandlerController.java | 10 ++- ...ttributeQueryProfileHandlerController.java | 10 ++- .../saml/web/SamlValidateEndpoint.java | 10 ++- 26 files changed, 418 insertions(+), 213 deletions(-) create mode 100644 api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameProviderContext.java create mode 100644 support/cas-server-support-json-service-registry/src/test/resources/UsernameAttrRelease-100.json diff --git a/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameAttributeProvider.java b/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameAttributeProvider.java index c8f62000a868..356ca91a1893 100644 --- a/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameAttributeProvider.java +++ b/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameAttributeProvider.java @@ -1,8 +1,5 @@ package org.apereo.cas.services; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; - import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.io.Serializable; @@ -20,10 +17,8 @@ public interface RegisteredServiceUsernameAttributeProvider extends Serializable /** * Resolve the username that is to be returned to CAS clients. * - * @param principal the principal - * @param service the service for which attribute should be calculated - * @param registeredService the registered service owning this user name attribute provider + * @param context the context * @return the username value configured for this service */ - String resolveUsername(Principal principal, Service service, RegisteredService registeredService); + String resolveUsername(RegisteredServiceUsernameProviderContext context); } diff --git a/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameProviderContext.java b/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameProviderContext.java new file mode 100644 index 000000000000..2b0b0899e59d --- /dev/null +++ b/api/cas-server-core-api-services/src/main/java/org/apereo/cas/services/RegisteredServiceUsernameProviderContext.java @@ -0,0 +1,32 @@ +package org.apereo.cas.services; + +import org.apereo.cas.authentication.principal.Principal; +import org.apereo.cas.authentication.principal.Service; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.With; +import lombok.experimental.SuperBuilder; + +import java.util.List; +import java.util.Map; + +/** + * This is {@link RegisteredServiceUsernameProviderContext}. + * + * @author Misagh Moayyed + * @since 6.5.0 + */ +@SuperBuilder +@Getter +@With +@AllArgsConstructor +public class RegisteredServiceUsernameProviderContext { + private final Principal principal; + + private final Service service; + + private final RegisteredService registeredService; + + private final Map> releasingAttributes; +} diff --git a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java index f8220218a383..d79cfb094f1d 100644 --- a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java +++ b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java @@ -5,6 +5,7 @@ import org.apereo.cas.authentication.principal.PrincipalFactory; import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.services.RegisteredService; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.util.CollectionUtils; import org.apereo.cas.util.function.FunctionUtils; @@ -75,15 +76,9 @@ public DefaultAuthenticationBuilder() { this.authenticationDate = ZonedDateTime.now(ZoneOffset.UTC); } - /** - * Creates a new instance using the current date for the authentication date and the given - * principal for the authenticated principal. - * - * @param p Authenticated principal. - */ - public DefaultAuthenticationBuilder(final Principal p) { + public DefaultAuthenticationBuilder(final Principal principal) { this(); - this.principal = p; + this.principal = principal; } /** @@ -129,8 +124,12 @@ public static AuthenticationBuilder of(final Principal principal, final Service service, final RegisteredService registeredService, final Authentication authentication) { - - val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(principal, service, registeredService); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .service(service) + .principal(principal) + .registeredService(registeredService) + .build(); + val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); val newPrincipal = principalFactory.createPrincipal(principalId, principalAttributes); return DefaultAuthenticationBuilder.newInstance(authentication).setPrincipal(newPrincipal); } diff --git a/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java b/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java index 4d06590eae92..47dad8b295d2 100644 --- a/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java +++ b/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java @@ -3,7 +3,6 @@ import org.apereo.cas.authentication.principal.DefaultPrincipalAttributesRepository; import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.authentication.principal.RegisteredServicePrincipalAttributesRepository; -import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.services.consent.DefaultRegisteredServiceConsentPolicy; import org.apereo.cas.util.CollectionUtils; import org.apereo.cas.util.RegexUtils; @@ -123,8 +122,7 @@ public Map> getAttributes(final RegisteredServiceAttributeR } LOGGER.trace("Adding policy attributes to the released set of attributes"); attributesToRelease.putAll(policyAttributes); - insertPrincipalIdAsAttributeIfNeeded(context.getPrincipal(), - attributesToRelease, context.getService(), context.getRegisteredService()); + insertPrincipalIdAsAttributeIfNeeded(context, attributesToRelease); if (getAttributeFilter() != null) { LOGGER.debug("Invoking attribute filter [{}] on the final set of attributes", getAttributeFilter()); return getAttributeFilter().filter(attributesToRelease); @@ -193,23 +191,10 @@ public abstract Map> getAttributesInternal( RegisteredServiceAttributeReleasePolicyContext context, Map> attributes); - /** - * Supports this policy request.. - * - * @param context the context - * @return true/false - */ protected boolean supports(final RegisteredServiceAttributeReleasePolicyContext context) { return true; } - /** - * Resolve attributes from attribute definition store and provide map. - * - * @param context the context - * @param principalAttributes the principal attributes - * @return the map - */ protected Map> resolveAttributesFromAttributeDefinitionStore( final RegisteredServiceAttributeReleasePolicyContext context, final Map> principalAttributes) { @@ -237,13 +222,6 @@ protected Map> resolveAttributesFromAttributeDefinitionStor }); } - /** - * Resolve attributes from principal attribute repository. - * - * @param principal the principal - * @param registeredService the registered service - * @return the map - */ protected Map> resolveAttributesFromPrincipalAttributeRepository(final Principal principal, final RegisteredService registeredService) { val attributes = getRegisteredServicePrincipalAttributesRepository() @@ -256,35 +234,27 @@ protected Map> resolveAttributesFromPrincipalAttributeRepos return attributes; } - /** - * Release principal id as attribute if needed. - * - * @param principal the principal - * @param attributesToRelease the attributes to release - * @param service the service - * @param registeredService the registered service - */ - protected void insertPrincipalIdAsAttributeIfNeeded(final Principal principal, final Map> attributesToRelease, - final Service service, final RegisteredService registeredService) { + protected void insertPrincipalIdAsAttributeIfNeeded(final RegisteredServiceAttributeReleasePolicyContext context, + final Map> attributesToRelease) { if (StringUtils.isNotBlank(getPrincipalIdAttribute())) { - LOGGER.debug("Attempting to resolve the principal id for service [{}]", registeredService.getServiceId()); - val usernameProvider = registeredService.getUsernameAttributeProvider(); + LOGGER.debug("Attempting to resolve the principal id for service [{}]", context.getRegisteredService().getServiceId()); + val usernameProvider = context.getRegisteredService().getUsernameAttributeProvider(); if (usernameProvider != null) { - val id = usernameProvider.resolveUsername(principal, service, registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .service(context.getService()) + .principal(context.getPrincipal()) + .registeredService(context.getRegisteredService()) + .releasingAttributes(attributesToRelease) + .build(); + + val id = usernameProvider.resolveUsername(usernameContext); LOGGER.debug("Releasing resolved principal id [{}] as attribute [{}]", id, getPrincipalIdAttribute()); - attributesToRelease.put(getPrincipalIdAttribute(), CollectionUtils.wrapList(principal.getId())); + attributesToRelease.put(getPrincipalIdAttribute(), CollectionUtils.wrapList(context.getPrincipal().getId())); } } } - /** - * Return the final attributes collection. - * Subclasses may override this minute to impose last minute rules. - * - * @param attributesToRelease the attributes to release - * @param service the service - * @return the map - */ protected Map> returnFinalAttributesCollection(final Map> attributesToRelease, final RegisteredService service) { LOGGER.debug("Final collection of attributes allowed are: [{}]", attributesToRelease); diff --git a/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/RegisteredServiceAttributeReleasePolicyTests.java b/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/RegisteredServiceAttributeReleasePolicyTests.java index 2d9fb3d96562..f82b64ad855c 100644 --- a/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/RegisteredServiceAttributeReleasePolicyTests.java +++ b/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/RegisteredServiceAttributeReleasePolicyTests.java @@ -7,7 +7,6 @@ import org.apereo.cas.authentication.principal.PrincipalFactoryUtils; import org.apereo.cas.authentication.principal.PrincipalResolver; import org.apereo.cas.authentication.principal.RegisteredServicePrincipalAttributesRepository; -import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.authentication.principal.cache.CachingPrincipalAttributesRepository; import org.apereo.cas.config.CasCoreUtilConfiguration; import org.apereo.cas.util.CollectionUtils; @@ -229,8 +228,8 @@ public void verifyServiceAttributeFilterAllAttributes() { private static final long serialVersionUID = 771643288929352964L; @Override - public String resolveUsername(final Principal principal, final Service service, final RegisteredService registeredService) { - return principal.getId(); + public String resolveUsername(final RegisteredServiceUsernameProviderContext context) { + return context.getPrincipal().getId(); } }); val context = RegisteredServiceAttributeReleasePolicyContext.builder() diff --git a/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/ReturnAllowedAttributeReleasePolicyTests.java b/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/ReturnAllowedAttributeReleasePolicyTests.java index 9d1387936bba..8c12e3599ae3 100644 --- a/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/ReturnAllowedAttributeReleasePolicyTests.java +++ b/core/cas-server-core-authentication-attributes/src/test/java/org/apereo/cas/services/ReturnAllowedAttributeReleasePolicyTests.java @@ -4,8 +4,6 @@ import org.apereo.cas.authentication.attribute.AttributeDefinitionStore; import org.apereo.cas.authentication.attribute.DefaultAttributeDefinition; import org.apereo.cas.authentication.attribute.DefaultAttributeDefinitionStore; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.config.CasCoreUtilConfiguration; import org.apereo.cas.config.CasPersonDirectoryTestConfiguration; import org.apereo.cas.configuration.CasConfigurationProperties; @@ -286,8 +284,8 @@ public void verifyDefaultAttributes() { private static final long serialVersionUID = 6935950848419028873L; @Override - public String resolveUsername(final Principal principal, final Service service, final RegisteredService registeredService) { - return principal.getId(); + public String resolveUsername(final RegisteredServiceUsernameProviderContext context) { + return context.getPrincipal().getId(); } }); diff --git a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProvider.java b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProvider.java index 010867e6a9ed..828e119425f7 100644 --- a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProvider.java +++ b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProvider.java @@ -1,8 +1,6 @@ package org.apereo.cas.services; import org.apereo.cas.authentication.principal.PersistentIdGenerator; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.authentication.principal.ShibbolethCompatiblePersistentIdGenerator; import org.apereo.cas.util.RandomUtils; @@ -44,8 +42,8 @@ public class AnonymousRegisteredServiceUsernameAttributeProvider extends BaseReg private PersistentIdGenerator persistentIdGenerator = new ShibbolethCompatiblePersistentIdGenerator(RandomUtils.randomAlphanumeric(16)); @Override - protected String resolveUsernameInternal(final Principal principal, final Service service, final RegisteredService registeredService) { - val id = this.persistentIdGenerator.generate(principal, service); + protected String resolveUsernameInternal(final RegisteredServiceUsernameProviderContext context) { + val id = this.persistentIdGenerator.generate(context.getPrincipal(), context.getService()); LOGGER.debug("Resolved username [{}] for anonymous access", id); return id; } diff --git a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java index a13cbbd90b8b..de7bd2f32e06 100644 --- a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java +++ b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java @@ -1,7 +1,5 @@ package org.apereo.cas.services; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.util.function.FunctionUtils; import org.apereo.cas.util.spring.ApplicationContextProvider; @@ -49,21 +47,21 @@ public abstract class BaseRegisteredServiceUsernameAttributeProvider implements private String removePattern; @Override - public final String resolveUsername(final Principal principal, final Service service, final RegisteredService registeredService) { - val resolvedUsername = resolveUsernameInternal(principal, service, registeredService); + public final String resolveUsername(final RegisteredServiceUsernameProviderContext context) { + val resolvedUsername = resolveUsernameInternal(context); if (canonicalizationMode == null) { canonicalizationMode = CaseCanonicalizationMode.NONE.name(); } val removedUsername = removePatternFromUsernameIfNecessary(resolvedUsername); val finalUsername = scopeUsernameIfNecessary(removedUsername); val uid = CaseCanonicalizationMode.valueOf(canonicalizationMode).canonicalize(finalUsername.trim(), Locale.getDefault()); - LOGGER.debug("Resolved username for [{}] is [{}]", service, uid); + LOGGER.debug("Resolved username for [{}] is [{}]", context.getService(), uid); if (!this.encryptUsername) { return uid; } - val encryptedId = encryptResolvedUsername(principal, service, registeredService, uid); + val encryptedId = encryptResolvedUsername(context, uid); if (StringUtils.isBlank(encryptedId)) { - throw new IllegalArgumentException("Could not encrypt username " + uid + " for service " + service); + throw new IllegalArgumentException("Could not encrypt username " + uid + " for service " + context.getService()); } return encryptedId; } @@ -88,26 +86,22 @@ protected String scopeUsernameIfNecessary(final String resolved) { /** * Encrypt resolved username. * - * @param principal the principal - * @param service the service - * @param registeredService the registered service - * @param username the username + * @param context the context + * @param username the username * @return the encrypted username or null */ - protected String encryptResolvedUsername(final Principal principal, final Service service, final RegisteredService registeredService, final String username) { + protected String encryptResolvedUsername(final RegisteredServiceUsernameProviderContext context, final String username) { val applicationContext = ApplicationContextProvider.getApplicationContext(); val cipher = applicationContext.getBean(RegisteredServiceCipherExecutor.DEFAULT_BEAN_NAME, RegisteredServiceCipherExecutor.class); - return cipher.encode(username, Optional.of(registeredService)); + return cipher.encode(username, Optional.of(context.getRegisteredService())); } /** * Resolve username internal string. * - * @param principal the principal - * @param service the service - * @param registeredService the registered service + * @param context the context * @return the string */ - protected abstract String resolveUsernameInternal(Principal principal, Service service, RegisteredService registeredService); + protected abstract String resolveUsernameInternal(RegisteredServiceUsernameProviderContext context); } diff --git a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProvider.java b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProvider.java index 7f2dc5d293a1..a27fbcfb09c5 100644 --- a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProvider.java +++ b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProvider.java @@ -1,8 +1,5 @@ package org.apereo.cas.services; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; - import com.fasterxml.jackson.annotation.JsonInclude; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -28,8 +25,8 @@ public class DefaultRegisteredServiceUsernameProvider extends BaseRegisteredServ private static final long serialVersionUID = 5823989148794052951L; @Override - public String resolveUsernameInternal(final Principal principal, final Service service, final RegisteredService registeredService) { - LOGGER.debug("Returning the default principal id [{}] for username.", principal.getId()); - return principal.getId(); + public String resolveUsernameInternal(final RegisteredServiceUsernameProviderContext context) { + LOGGER.debug("Returning the default principal id [{}] for username.", context.getPrincipal().getId()); + return context.getPrincipal().getId(); } } diff --git a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProvider.java b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProvider.java index 972812abcff6..20f7673734e6 100644 --- a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProvider.java +++ b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProvider.java @@ -42,31 +42,31 @@ public GroovyRegisteredServiceUsernameProvider(@JsonProperty("groovyScript") fin this.groovyScript = script; } - private static String fetchAttributeValue(final Principal principal, - final Service service, - final RegisteredService registeredService, + private static String fetchAttributeValue(final RegisteredServiceUsernameProviderContext context, final String groovyScript) { return ApplicationContextProvider.getScriptResourceCacheManager() .map(cacheMgr -> { - val script = cacheMgr.resolveScriptableResource(groovyScript, registeredService.getServiceId(), registeredService.getName()); - return fetchAttributeValueFromScript(script, principal, service); + val script = cacheMgr.resolveScriptableResource(groovyScript, + context.getRegisteredService().getServiceId(), context.getRegisteredService().getName()); + return fetchAttributeValueFromScript(script, context.getPrincipal(), context.getService()); }) .map(Object::toString) .orElseThrow(() -> new RuntimeException("No groovy script cache manager is available to execute username provider")); } @Override - public String resolveUsernameInternal(final Principal principal, final Service service, final RegisteredService registeredService) { + public String resolveUsernameInternal(final RegisteredServiceUsernameProviderContext context) { if (StringUtils.isNotBlank(this.groovyScript)) { - val result = fetchAttributeValue(principal, service, registeredService, groovyScript); + val result = fetchAttributeValue(context, groovyScript); if (result != null) { LOGGER.debug("Found username [{}] from script", result); return result; } } - LOGGER.warn("Groovy script [{}] is not valid. CAS will switch to use the default principal identifier [{}]", this.groovyScript, principal.getId()); - return principal.getId(); + LOGGER.warn("Groovy script [{}] is not valid. CAS will switch to use the default principal identifier [{}]", + this.groovyScript, context.getPrincipal().getId()); + return context.getPrincipal().getId(); } private static Object fetchAttributeValueFromScript(final ExecutableCompiledGroovyScript script, diff --git a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProvider.java b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProvider.java index 92c18ed87f07..0eaf477218c7 100644 --- a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProvider.java +++ b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProvider.java @@ -1,8 +1,7 @@ package org.apereo.cas.services; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.util.CollectionUtils; +import org.apereo.cas.util.function.FunctionUtils; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; @@ -45,69 +44,65 @@ public class PrincipalAttributeRegisteredServiceUsernameProvider extends BaseReg private String usernameAttribute; @Override - public String resolveUsernameInternal(final Principal principal, final Service service, final RegisteredService registeredService) { - var principalId = principal.getId(); + public String resolveUsernameInternal(final RegisteredServiceUsernameProviderContext context) { + var principalId = context.getPrincipal().getId(); val originalPrincipalAttributes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - originalPrincipalAttributes.putAll(principal.getAttributes()); - LOGGER.debug("Original principal attributes available for selection of username attribute [{}] are [{}].", this.usernameAttribute, originalPrincipalAttributes); + originalPrincipalAttributes.putAll(context.getPrincipal().getAttributes()); + LOGGER.debug("Original principal attributes available for selection of username attribute [{}] are [{}].", + usernameAttribute, originalPrincipalAttributes); val releasePolicyAttributes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - releasePolicyAttributes.putAll(getPrincipalAttributesFromReleasePolicy(principal, service, registeredService)); + + FunctionUtils.doIfNull(context.getReleasingAttributes(), + __ -> releasePolicyAttributes.putAll(getPrincipalAttributesFromReleasePolicy(context)), + releasePolicyAttributes::putAll); + LOGGER.debug("Attributes resolved by the release policy available for selection of username attribute [{}] are [{}].", - this.usernameAttribute, releasePolicyAttributes); + usernameAttribute, releasePolicyAttributes); - if (StringUtils.isBlank(this.usernameAttribute)) { + if (StringUtils.isBlank(usernameAttribute)) { LOGGER.warn("No username attribute is defined for service [{}]. CAS will fall back onto using the default principal id. " - + "This is likely a mistake in the configuration of the registered service definition.", registeredService.getName()); - } else if (releasePolicyAttributes.containsKey(this.usernameAttribute)) { + + "This is likely a mistake in the configuration of the registered service definition.", context.getRegisteredService().getName()); + } else if (releasePolicyAttributes.containsKey(usernameAttribute)) { LOGGER.debug("Attribute release policy for registered service [{}] contains an attribute for [{}]", - registeredService.getServiceId(), this.usernameAttribute); - val value = releasePolicyAttributes.get(this.usernameAttribute); + context.getRegisteredService().getServiceId(), usernameAttribute); + val value = releasePolicyAttributes.get(usernameAttribute); principalId = CollectionUtils.wrap(value).get(0).toString(); - } else if (originalPrincipalAttributes.containsKey(this.usernameAttribute)) { + } else if (originalPrincipalAttributes.containsKey(usernameAttribute)) { LOGGER.debug("The selected username attribute [{}] was retrieved as a direct " + "principal attribute and not through the attribute release policy for service [{}]. " + "CAS is unable to detect new attribute values for [{}] after authentication unless the attribute " + "is explicitly authorized for release via the service attribute release policy.", - this.usernameAttribute, service, this.usernameAttribute); - val value = originalPrincipalAttributes.get(this.usernameAttribute); + usernameAttribute, context.getService(), usernameAttribute); + val value = originalPrincipalAttributes.get(usernameAttribute); principalId = CollectionUtils.wrap(value).get(0).toString(); } else { LOGGER.info("Principal [{}] does not have an attribute [{}] among attributes [{}] so CAS cannot " + "provide the user attribute the service expects. " + "CAS will instead return the default principal id [{}]. Ensure the attribute selected as the username " - + "is allowed to be released by the service attribute release policy.", principalId, this.usernameAttribute, releasePolicyAttributes, principalId); + + "is allowed to be released by the service attribute release policy.", principalId, usernameAttribute, releasePolicyAttributes, principalId); } - LOGGER.debug("Principal id to return for [{}] is [{}]. The default principal id is [{}].", service.getId(), principalId, principal.getId()); + LOGGER.debug("Principal id to return for [{}] is [{}]. The default principal id is [{}].", context.getService().getId(), + principalId, context.getPrincipal().getId()); return principalId.trim(); } - /** - * Gets principal attributes. Will attempt to locate the principal - * attribute repository from the context if one is defined to use - * that instance to locate attributes. If none is available, - * will use the default principal attributes. - * - * @param principal the principal - * @param service the service - * @param registeredService the registered service - * @return the principal attributes - */ protected Map> getPrincipalAttributesFromReleasePolicy( - final Principal principal, final Service service, final RegisteredService registeredService) { - if (registeredService != null && registeredService.getAccessStrategy().isServiceAccessAllowed()) { - LOGGER.debug("Located service [{}] in the registry. Attempting to resolve attributes for [{}]", registeredService, principal.getId()); - if (registeredService.getAttributeReleasePolicy() == null) { - LOGGER.debug("No attribute release policy is defined for [{}]. Returning default principal attributes", service.getId()); - return principal.getAttributes(); + final RegisteredServiceUsernameProviderContext context) { + if (context.getRegisteredService() != null && context.getRegisteredService().getAccessStrategy().isServiceAccessAllowed()) { + LOGGER.debug("Located service [{}] in the registry. Attempting to resolve attributes for [{}]", + context.getRegisteredService(), context.getPrincipal().getId()); + if (context.getRegisteredService().getAttributeReleasePolicy() == null) { + LOGGER.debug("No attribute release policy is defined for [{}]. Returning default principal attributes", context.getService().getId()); + return context.getPrincipal().getAttributes(); } - val context = RegisteredServiceAttributeReleasePolicyContext.builder() - .registeredService(registeredService) - .service(service) - .principal(principal) + val releasePolicyContext = RegisteredServiceAttributeReleasePolicyContext.builder() + .registeredService(context.getRegisteredService()) + .service(context.getService()) + .principal(context.getPrincipal()) .build(); - return registeredService.getAttributeReleasePolicy().getAttributes(context); + return context.getRegisteredService().getAttributeReleasePolicy().getAttributes(releasePolicyContext); } - LOGGER.debug("Could not locate service [{}] in the registry.", service.getId()); + LOGGER.debug("Could not locate service [{}] in the registry.", context.getService().getId()); throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE); } } diff --git a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProviderTests.java b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProviderTests.java index 97f7c268d7f1..0f4e62b6f960 100644 --- a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProviderTests.java +++ b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/AnonymousRegisteredServiceUsernameAttributeProviderTests.java @@ -43,7 +43,14 @@ public void verifyPrincipalResolution() { when(service.getId()).thenReturn("id"); val principal = mock(Principal.class); when(principal.getId()).thenReturn("uid"); - val id = provider.resolveUsername(principal, service, RegisteredServiceTestUtils.getRegisteredService("id")); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("id")) + .service(service) + .principal(principal) + .build(); + + val id = provider.resolveUsername(usernameContext); assertNotNull(id); } @@ -74,10 +81,14 @@ public void verifyGeneratedIdsMatch() { val gen = new ShibbolethCompatiblePersistentIdGenerator(salt); gen.setAttribute("employeeId"); val provider = new AnonymousRegisteredServiceUsernameAttributeProvider(gen); - val result = provider.resolveUsername(CoreAuthenticationTestUtils.getPrincipal("anyuser", - CollectionUtils.wrap("employeeId", List.of("T911327"))), - CoreAuthenticationTestUtils.getService("https://cas.example.org/app"), - CoreAuthenticationTestUtils.getRegisteredService()); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(CoreAuthenticationTestUtils.getRegisteredService()) + .service(CoreAuthenticationTestUtils.getService("https://cas.example.org/app")) + .principal(CoreAuthenticationTestUtils.getPrincipal("anyuser", + CollectionUtils.wrap("employeeId", List.of("T911327")))) + .build(); + val result = provider.resolveUsername(usernameContext); assertEquals("ujWTRNKPPso8S+4geOvcOZtv778=", result); } @@ -87,10 +98,14 @@ public void verifyGeneratedIdsMatchMultiValuedAttribute() { val gen = new ShibbolethCompatiblePersistentIdGenerator(salt); gen.setAttribute("uid"); val provider = new AnonymousRegisteredServiceUsernameAttributeProvider(gen); - val result = provider.resolveUsername(CoreAuthenticationTestUtils.getPrincipal("anyuser", - CollectionUtils.wrap("uid", CollectionUtils.wrap("obegon"))), - CoreAuthenticationTestUtils.getService("https://sp.testshib.org/shibboleth-sp"), - CoreAuthenticationTestUtils.getRegisteredService()); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(CoreAuthenticationTestUtils.getRegisteredService()) + .service(CoreAuthenticationTestUtils.getService("https://sp.testshib.org/shibboleth-sp")) + .principal(CoreAuthenticationTestUtils.getPrincipal("anyuser", + CollectionUtils.wrap("uid", CollectionUtils.wrap("obegon")))) + .build(); + val result = provider.resolveUsername(usernameContext); assertEquals("lykoGRE9QbbrsEBlHJVEz0U8AJ0=", result); } } diff --git a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProviderTests.java b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProviderTests.java index fba91dd27fbf..d14398451c32 100644 --- a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProviderTests.java +++ b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/DefaultRegisteredServiceUsernameProviderTests.java @@ -42,7 +42,14 @@ public void verifyNoCanonAndEncrypt() { provider.setEncryptUsername(true); val principal = RegisteredServiceTestUtils.getPrincipal("ID"); val service = RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService"); - val id = provider.resolveUsername(principal, RegisteredServiceTestUtils.getService(), service); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(service) + .service(RegisteredServiceTestUtils.getService()) + .principal(principal) + .build(); + + val id = provider.resolveUsername(usernameContext); provider.initialize(); assertEquals(id, principal.getId().toUpperCase()); } @@ -52,8 +59,13 @@ public void verifyRegServiceUsernameUpper() { val provider = new DefaultRegisteredServiceUsernameProvider(); provider.setCanonicalizationMode(CaseCanonicalizationMode.UPPER.name()); val principal = RegisteredServiceTestUtils.getPrincipal("id"); - val id = provider.resolveUsername(principal, RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService()) + .principal(principal) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals(id, principal.getId().toUpperCase()); } @@ -63,8 +75,13 @@ public void verifyPatternRemoval() { provider.setCanonicalizationMode(CaseCanonicalizationMode.UPPER.name()); provider.setRemovePattern("@.+"); val principal = RegisteredServiceTestUtils.getPrincipal("casuser@example.org"); - val id = provider.resolveUsername(principal, RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService()) + .principal(principal) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals(id, "CASUSER"); } @@ -74,8 +91,13 @@ public void verifyScopedUsername() { provider.setCanonicalizationMode(CaseCanonicalizationMode.UPPER.name()); provider.setScope("example.org"); val principal = RegisteredServiceTestUtils.getPrincipal("id"); - val id = provider.resolveUsername(principal, RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService()) + .principal(principal) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals(id, principal.getId().toUpperCase().concat("@EXAMPLE.ORG")); } @@ -83,8 +105,13 @@ public void verifyScopedUsername() { public void verifyRegServiceUsername() { val provider = new DefaultRegisteredServiceUsernameProvider(); val principal = RegisteredServiceTestUtils.getPrincipal("id"); - val id = provider.resolveUsername(principal, RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService("id")); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("id")) + .service(RegisteredServiceTestUtils.getService()) + .principal(principal) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals(id, principal.getId()); } diff --git a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java index 97c9e2e1a5f1..e5875ac9b46c 100644 --- a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java +++ b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java @@ -14,7 +14,6 @@ import java.io.File; import java.io.IOException; -import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -39,8 +38,13 @@ public class GroovyRegisteredServiceUsernameProviderTests { public void verifyUsernameProvider() { val p = new GroovyRegisteredServiceUsernameProvider(); p.setGroovyScript("classpath:uid.groovy"); - val id = p.resolveUsername(RegisteredServiceTestUtils.getPrincipal(), RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService()); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService()) + .service(RegisteredServiceTestUtils.getService()) + .principal(RegisteredServiceTestUtils.getPrincipal()) + .build(); + val id = p.resolveUsername(usernameContext); assertEquals("fromscript", id); } @@ -48,9 +52,13 @@ public void verifyUsernameProvider() { public void verifyUsernameProviderInline() { val p = new GroovyRegisteredServiceUsernameProvider(); p.setGroovyScript("groovy { return attributes['uid'] + '123456789' }"); - var id = p.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser", - CollectionUtils.wrap("uid", "CAS-System")), RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService()); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService()) + .service(RegisteredServiceTestUtils.getService()) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser", CollectionUtils.wrap("uid", "CAS-System"))) + .build(); + val id = p.resolveUsername(usernameContext); assertEquals("CAS-System123456789", id); } @@ -58,9 +66,12 @@ public void verifyUsernameProviderInline() { public void verifyUsernameProviderInlineAsList() { val p = new GroovyRegisteredServiceUsernameProvider(); p.setGroovyScript("groovy { return attributes['uid'][0] + '123456789' }"); - var id = p.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser", - CollectionUtils.wrap("uid", List.of("CAS-System"))), RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService()); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService()) + .service(RegisteredServiceTestUtils.getService()) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser", CollectionUtils.wrap("uid", "CAS-System"))) + .build(); + val id = p.resolveUsername(usernameContext); assertEquals("CAS-System123456789", id); } diff --git a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java index 4094544e9092..41692561062e 100644 --- a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java +++ b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java @@ -53,8 +53,13 @@ public void verifyUsernameByPrincipalAttributeWithMapping() { val principalAttributes = new HashMap>(); principalAttributes.put("email", List.of("user@example.org")); val p = RegisteredServiceTestUtils.getPrincipal("person", principalAttributes); - val id = provider.resolveUsername(p, - RegisteredServiceTestUtils.getService("verifyUsernameByPrincipalAttributeWithMapping"), registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(RegisteredServiceTestUtils.getService("verifyUsernameByPrincipalAttributeWithMapping")) + .principal(p) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals("user@example.org", id); } @@ -69,8 +74,12 @@ public void verifyUsernameByPrincipalAttributeAsCollection() { val p = RegisteredServiceTestUtils.getPrincipal("person", attrs); - val id = provider.resolveUsername(p, RegisteredServiceTestUtils.getService("usernameAttributeProviderService"), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) + .principal(p) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals("TheName", id); } @@ -82,9 +91,13 @@ public void verifyUsernameByPrincipalAttribute() { attrs.put("userid", List.of("u1")); attrs.put("cn", List.of("TheName")); - val p = RegisteredServiceTestUtils.getPrincipal("person", attrs); - val id = provider.resolveUsername(p, RegisteredServiceTestUtils.getService("usernameAttributeProviderService"), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + val principal = RegisteredServiceTestUtils.getPrincipal("person", attrs); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) + .principal(principal) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals("TheName", id); } @@ -100,7 +113,13 @@ public void verifyNoAttrRelPolicy() { val service = RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService"); service.setAttributeReleasePolicy(null); - val id = provider.resolveUsername(p, RegisteredServiceTestUtils.getService("usernameAttributeProviderService"), service); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) + .principal(p) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals("TheName", id); } @@ -117,8 +136,13 @@ public void verifyDisabledService() { val service = RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService"); service.setAccessStrategy(new DefaultRegisteredServiceAccessStrategy(false, false)); service.setAttributeReleasePolicy(null); - assertThrows(UnauthorizedServiceException.class, - () -> provider.resolveUsername(p, RegisteredServiceTestUtils.getService("usernameAttributeProviderService"), service)); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(service) + .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) + .principal(p) + .build(); + assertThrows(UnauthorizedServiceException.class, () -> provider.resolveUsername(usernameContext)); } @Test @@ -130,8 +154,12 @@ public void verifyUsernameByPrincipalAttributeNotFound() { val p = RegisteredServiceTestUtils.getPrincipal("person", attrs); - val id = provider.resolveUsername(p, RegisteredServiceTestUtils.getService("usernameAttributeProviderService"), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) + .principal(p) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals(id, p.getId()); } @@ -139,8 +167,12 @@ public void verifyUsernameByPrincipalAttributeNotFound() { public void verifyUsernameUndefined() { val provider = new PrincipalAttributeRegisteredServiceUsernameProvider(); val p = RegisteredServiceTestUtils.getPrincipal("person"); - val id = provider.resolveUsername(p, RegisteredServiceTestUtils.getService("usernameAttributeProviderService"), - RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService")) + .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) + .principal(p) + .build(); + val id = provider.resolveUsername(usernameContext); assertEquals(id, p.getId()); } diff --git a/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java b/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java index b91c940feced..62f56ba53f13 100644 --- a/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java +++ b/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java @@ -252,9 +252,26 @@ public static void doIfNotNull(final T input, */ public static void doIfNull(final T input, final CheckedConsumer trueFunction) { + doIfNull(input, trueFunction, t -> { + }); + } + + /** + * Do if null. + * + * @param the type parameter + * @param input the input + * @param trueFunction the true function + * @param falseFunction the false function + */ + public static void doIfNull(final T input, + final CheckedConsumer trueFunction, + final CheckedConsumer falseFunction) { try { if (input == null) { trueFunction.accept(null); + } else { + falseFunction.accept(input); } } catch (final Throwable e) { LoggingUtils.warn(LOGGER, e); diff --git a/support/cas-server-support-json-service-registry/src/test/java/org/apereo/cas/services/JsonServiceRegistryTests.java b/support/cas-server-support-json-service-registry/src/test/java/org/apereo/cas/services/JsonServiceRegistryTests.java index e8afb8495c98..9ad6987b86fd 100644 --- a/support/cas-server-support-json-service-registry/src/test/java/org/apereo/cas/services/JsonServiceRegistryTests.java +++ b/support/cas-server-support-json-service-registry/src/test/java/org/apereo/cas/services/JsonServiceRegistryTests.java @@ -1,5 +1,6 @@ package org.apereo.cas.services; +import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.config.CasCoreUtilConfiguration; import org.apereo.cas.services.replication.NoOpRegisteredServiceReplicationStrategy; import org.apereo.cas.services.resource.DefaultRegisteredServiceResourceNamingStrategy; @@ -16,6 +17,8 @@ import org.springframework.core.io.ClassPathResource; import java.util.ArrayList; +import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.*; @@ -94,4 +97,32 @@ public void verifyExistingDefinitionForCompatibility1() throws Exception { assertNotNull(policy); assertEquals(2, policy.getAllowedAttributes().size()); } + + @Test + public void verifyUsernameProviderWithAttributeReleasePolicy() throws Exception { + val appCtx = new StaticApplicationContext(); + appCtx.refresh(); + val resource = new ClassPathResource("UsernameAttrRelease-100.json"); + val serializer = new RegisteredServiceJsonSerializer(appCtx); + val service = serializer.from(resource.getInputStream()); + val context = RegisteredServiceAttributeReleasePolicyContext.builder() + .registeredService(service) + .service(CoreAuthenticationTestUtils.getService()) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser", + Map.of("groups", List.of("g1", "g2"), "username", List.of("casuser")))) + .build(); + val attributes = service.getAttributeReleasePolicy().getAttributes(context); + assertEquals(3, attributes.size()); + assertTrue(attributes.containsKey("groups")); + assertTrue(attributes.containsKey("username")); + assertTrue(attributes.containsKey("familyName")); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(context.getRegisteredService()) + .service(context.getService()) + .principal(context.getPrincipal()) + .build(); + val username = service.getUsernameAttributeProvider().resolveUsername(usernameContext); + assertEquals("casuser", username); + } } diff --git a/support/cas-server-support-json-service-registry/src/test/resources/UsernameAttrRelease-100.json b/support/cas-server-support-json-service-registry/src/test/resources/UsernameAttrRelease-100.json new file mode 100644 index 000000000000..a81940193219 --- /dev/null +++ b/support/cas-server-support-json-service-registry/src/test/resources/UsernameAttrRelease-100.json @@ -0,0 +1,40 @@ +{ + "@class": "org.apereo.cas.services.CasRegisteredService", + "serviceId": "^http(s)?://.*/demo/std.*", + "name": "UsernameAttrRelease", + "id": 100, + "usernameAttributeProvider": { + "@class": "org.apereo.cas.services.PrincipalAttributeRegisteredServiceUsernameProvider", + "usernameAttribute": "internal" + }, + "attributeReleasePolicy": { + "@class": "org.apereo.cas.services.ChainingAttributeReleasePolicy", + "policies": [ + "java.util.ArrayList", + [ + { + "@class": "org.apereo.cas.services.ReturnMappedAttributeReleasePolicy", + "principalIdAttribute": "familyName", + "allowedAttributes": { + "@class": "java.util.TreeMap", + "fiscalNumber": "cf", + "groups": "groovy { if(attributes['groups'] != null && (attributes['groups'].contains('cn=mqax') || attributes['groups'].contains('CN=POLO GIURIDICO'))) return ['MQAX','MQAX1'] else ['SGP']}", + "username": "groovy { if(attributes['username'] != null) return attributes['username'] else attributes['mituid']; }" + } + }, + { + "@class": "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy", + "allowedAttributes": [ + "java.util.ArrayList", + [ + "username", + "internal", + "familyName" + ] + ] + } + ] + ] + } +} + diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20ClientIdClientSecretAuthenticator.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20ClientIdClientSecretAuthenticator.java index 2f08f9cdcde0..eb162e90a8d0 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20ClientIdClientSecretAuthenticator.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20ClientIdClientSecretAuthenticator.java @@ -7,6 +7,7 @@ import org.apereo.cas.authentication.principal.ServiceFactory; import org.apereo.cas.authentication.principal.WebApplicationService; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicyContext; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.services.ServicesManager; import org.apereo.cas.support.oauth.OAuth20Constants; import org.apereo.cas.support.oauth.OAuth20GrantTypes; @@ -87,7 +88,13 @@ public Optional validate(final CallContext callContext, final Crede LOGGER.debug("No principal was resolved. Falling back to the username [{}] from the credentials.", id); profile.setId(id); } else { - val username = registeredService.getUsernameAttributeProvider().resolveUsername(principal, service, registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(service) + .principal(principal) + .build(); + val username = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); profile.setId(username); } profile.addAttribute(OAuth20Constants.CLIENT_ID, id); diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20UsernamePasswordAuthenticator.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20UsernamePasswordAuthenticator.java index ca9626477566..3d31e0035fcc 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20UsernamePasswordAuthenticator.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/authenticator/OAuth20UsernamePasswordAuthenticator.java @@ -5,6 +5,7 @@ import org.apereo.cas.authentication.principal.ServiceFactory; import org.apereo.cas.services.RegisteredServiceAccessStrategyUtils; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicyContext; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.services.ServicesManager; import org.apereo.cas.support.oauth.OAuth20Constants; import org.apereo.cas.support.oauth.util.OAuth20Utils; @@ -89,7 +90,14 @@ public Optional validate(final CallContext callContext, final Crede val attributes = Objects.requireNonNull(registeredService).getAttributeReleasePolicy().getAttributes(context); val profile = new CommonProfile(); - val id = registeredService.getUsernameAttributeProvider().resolveUsername(principal, service, registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(service) + .principal(principal) + .build(); + + val id = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); LOGGER.debug("Created profile id [{}]", id); profile.setId(id); diff --git a/support/cas-server-support-oidc-services/src/main/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProvider.java b/support/cas-server-support-oidc-services/src/main/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProvider.java index c6ae0bc07d3e..c1f95f923630 100644 --- a/support/cas-server-support-oidc-services/src/main/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProvider.java +++ b/support/cas-server-support-oidc-services/src/main/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProvider.java @@ -2,8 +2,6 @@ import org.apereo.cas.authentication.principal.OidcPairwisePersistentIdGenerator; import org.apereo.cas.authentication.principal.PersistentIdGenerator; -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.authentication.principal.Service; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -50,20 +48,19 @@ public class PairwiseOidcRegisteredServiceUsernameAttributeProvider extends Base private PersistentIdGenerator persistentIdGenerator = new OidcPairwisePersistentIdGenerator(); @Override - public String resolveUsernameInternal(final Principal principal, final Service service, - final RegisteredService registeredService) { - if (registeredService == null || !OidcRegisteredService.class.isAssignableFrom(registeredService.getClass())) { - LOGGER.warn("Service definition [{}] is undefined or it's not an OpenId Connect relying party", registeredService); - return principal.getId(); + public String resolveUsernameInternal(final RegisteredServiceUsernameProviderContext context) { + if (context.getRegisteredService() == null || !OidcRegisteredService.class.isAssignableFrom(context.getRegisteredService().getClass())) { + LOGGER.warn("Service definition [{}] is undefined or it's not an OpenId Connect relying party", context.getRegisteredService()); + return context.getPrincipal().getId(); } - val oidcSvc = (OidcRegisteredService) registeredService; + val oidcSvc = (OidcRegisteredService) context.getRegisteredService(); if (StringUtils.isBlank(oidcSvc.getSubjectType()) || StringUtils.equalsIgnoreCase(OidcSubjectTypes.PUBLIC.getType(), oidcSvc.getSubjectType())) { LOGGER.warn("Service definition [{}] does not request a pairwise subject type", oidcSvc); - return principal.getId(); + return context.getPrincipal().getId(); } val sectorIdentifier = getSectorIdentifier(oidcSvc); - val id = this.persistentIdGenerator.generate(principal, sectorIdentifier); + val id = this.persistentIdGenerator.generate(context.getPrincipal(), sectorIdentifier); LOGGER.debug("Resolved username [{}] for pairwise access", id); return id; } diff --git a/support/cas-server-support-oidc-services/src/test/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProviderTests.java b/support/cas-server-support-oidc-services/src/test/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProviderTests.java index b407b8bfaf87..d76329cce3b5 100644 --- a/support/cas-server-support-oidc-services/src/test/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProviderTests.java +++ b/support/cas-server-support-oidc-services/src/test/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProviderTests.java @@ -20,8 +20,13 @@ public class PairwiseOidcRegisteredServiceUsernameAttributeProviderTests { @Test public void verifyNonCompatibleService() { val provider = new PairwiseOidcRegisteredServiceUsernameAttributeProvider(); - val uid = provider.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser"), RegisteredServiceTestUtils.getService(), - RegisteredServiceTestUtils.getRegisteredService()); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(RegisteredServiceTestUtils.getRegisteredService()) + .service(RegisteredServiceTestUtils.getService("verifyUsernameByPrincipalAttributeWithMapping")) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser")) + .build(); + val uid = provider.resolveUsername(usernameContext); assertEquals("casuser", uid); } @@ -36,15 +41,21 @@ public void verifyUndefinedOrPublicSubjectType() { registeredService.setClientSecret("something"); registeredService.setSubjectType(StringUtils.EMPTY); - var uid = provider.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser"), RegisteredServiceTestUtils.getService(), registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(RegisteredServiceTestUtils.getService()) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser")) + .build(); + var uid = provider.resolveUsername(usernameContext); assertEquals("casuser", uid); registeredService.setSubjectType(null); - uid = provider.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser"), RegisteredServiceTestUtils.getService(), registeredService); + uid = provider.resolveUsername(usernameContext); assertEquals("casuser", uid); registeredService.setSubjectType(OidcSubjectTypes.PUBLIC.getType()); - uid = provider.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser"), RegisteredServiceTestUtils.getService(), registeredService); + uid = provider.resolveUsername(usernameContext); assertEquals("casuser", uid); } @@ -60,12 +71,18 @@ public void verifySubjectType() { registeredService.setClientSecret("something"); registeredService.setSubjectType(OidcSubjectTypes.PAIRWISE.getType()); - val uid = provider.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser"), RegisteredServiceTestUtils.getService(), registeredService); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(RegisteredServiceTestUtils.getService()) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser")) + .build(); + + val uid = provider.resolveUsername(usernameContext); assertEquals("9IOlxFj2XgfhkNJieynbw+Pm+4E=", uid); registeredService.setSectorIdentifierUri(null); registeredService.setServiceId("https://sso.example.org/oidc"); - val uid1 = provider.resolveUsername(RegisteredServiceTestUtils.getPrincipal("casuser"), RegisteredServiceTestUtils.getService(), registeredService); + val uid1 = provider.resolveUsername(usernameContext); assertEquals(uid1, uid); } } diff --git a/support/cas-server-support-saml-googleapps-core/src/main/java/org/apereo/cas/support/saml/authentication/principal/GoogleAccountsServiceResponseBuilder.java b/support/cas-server-support-saml-googleapps-core/src/main/java/org/apereo/cas/support/saml/authentication/principal/GoogleAccountsServiceResponseBuilder.java index c69b312746fb..c9596bb9960b 100644 --- a/support/cas-server-support-saml-googleapps-core/src/main/java/org/apereo/cas/support/saml/authentication/principal/GoogleAccountsServiceResponseBuilder.java +++ b/support/cas-server-support-saml-googleapps-core/src/main/java/org/apereo/cas/support/saml/authentication/principal/GoogleAccountsServiceResponseBuilder.java @@ -5,6 +5,7 @@ import org.apereo.cas.authentication.principal.Response; import org.apereo.cas.authentication.principal.WebApplicationService; import org.apereo.cas.configuration.support.Beans; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.services.ServicesManager; import org.apereo.cas.services.UnauthorizedServiceException; import org.apereo.cas.support.saml.SamlProtocolConstants; @@ -127,8 +128,13 @@ protected String constructSamlResponse(final GoogleAccountsService service, } val principal = authentication.getPrincipal(); - val userId = registeredService.getUsernameAttributeProvider() - .resolveUsername(principal, service, registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(service) + .principal(principal) + .build(); + val userId = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); val response = this.samlObjectBuilder.newResponse( this.samlObjectBuilder.generateSecureRandomId(), currentDateTime, null, service); diff --git a/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/AbstractSamlIdPProfileHandlerController.java b/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/AbstractSamlIdPProfileHandlerController.java index 3c49d314934b..5e94655ef474 100644 --- a/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/AbstractSamlIdPProfileHandlerController.java +++ b/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/AbstractSamlIdPProfileHandlerController.java @@ -8,6 +8,7 @@ import org.apereo.cas.configuration.model.core.web.session.SessionStorageTypes; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicyContext; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.services.UnauthorizedServiceException; import org.apereo.cas.support.saml.SamlException; import org.apereo.cas.support.saml.SamlIdPUtils; @@ -197,8 +198,13 @@ protected AuthenticatedAssertionContext buildCasAssertion(final Authentication a .principal(authentication.getPrincipal()) .build(); val attributes = registeredService.getAttributeReleasePolicy().getAttributes(context); - val principalId = registeredService.getUsernameAttributeProvider() - .resolveUsername(authentication.getPrincipal(), service, registeredService); + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(service) + .principal(authentication.getPrincipal()) + .build(); + val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); attributes.putAll(attributesToCombine); val authnAttributes = configurationContext.getAuthenticationAttributeReleasePolicy() diff --git a/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/query/SamlIdPSaml2AttributeQueryProfileHandlerController.java b/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/query/SamlIdPSaml2AttributeQueryProfileHandlerController.java index 296c0d5cde1d..da6fa8c55b7f 100644 --- a/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/query/SamlIdPSaml2AttributeQueryProfileHandlerController.java +++ b/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/query/SamlIdPSaml2AttributeQueryProfileHandlerController.java @@ -6,6 +6,7 @@ import org.apereo.cas.authentication.principal.PrincipalFactoryUtils; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicyContext; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.services.UnauthorizedServiceException; import org.apereo.cas.support.saml.SamlIdPConstants; import org.apereo.cas.support.saml.services.SamlRegisteredService; @@ -100,8 +101,13 @@ protected void handlePostRequest(final HttpServletResponse response, .getAuthenticationAttributesForRelease(authentication, null, Map.of(), registeredService); val finalAttributes = CollectionUtils.merge(principalAttributes, authenticationAttributes); - val principalId = registeredService.getUsernameAttributeProvider() - .resolveUsername(authentication.getPrincipal(), ticket.getService(), registeredService); + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(ticket.getService()) + .principal(authentication.getPrincipal()) + .build(); + + val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); LOGGER.debug("Principal id used for attribute query response should be [{}]", principalId); LOGGER.debug("Final attributes to be processed for the SAML2 response are [{}]", finalAttributes); diff --git a/support/cas-server-support-saml/src/main/java/org/apereo/cas/support/saml/web/SamlValidateEndpoint.java b/support/cas-server-support-saml/src/main/java/org/apereo/cas/support/saml/web/SamlValidateEndpoint.java index e9557f6b0dde..3cfffe8c59a7 100644 --- a/support/cas-server-support-saml/src/main/java/org/apereo/cas/support/saml/web/SamlValidateEndpoint.java +++ b/support/cas-server-support-saml/src/main/java/org/apereo/cas/support/saml/web/SamlValidateEndpoint.java @@ -11,6 +11,7 @@ import org.apereo.cas.authentication.principal.WebApplicationService; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicyContext; +import org.apereo.cas.services.RegisteredServiceUsernameProviderContext; import org.apereo.cas.services.ServicesManager; import org.apereo.cas.support.saml.OpenSamlConfigBean; import org.apereo.cas.support.saml.SamlUtils; @@ -103,7 +104,14 @@ public Map handle(final String username, final String password, .principal(principal) .build(); val attributesToRelease = registeredService.getAttributeReleasePolicy().getAttributes(context); - val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(principal, selectedService, registeredService); + + + val usernameContext = RegisteredServiceUsernameProviderContext.builder() + .registeredService(registeredService) + .service(selectedService) + .principal(principal) + .build(); + val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(usernameContext); val modifiedPrincipal = this.principalFactory.createPrincipal(principalId, attributesToRelease); From 739cc3cb23398bcbba338cc985718a9cfbcaff60 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 15 Mar 2023 11:54:29 +0400 Subject: [PATCH 009/266] enable monitoring of a few other core components --- core/cas-server-core-authentication-api/build.gradle | 1 + .../cas/authentication/AbstractAuthenticationHandler.java | 2 ++ core/cas-server-core-services-registry/build.gradle | 1 + .../java/org/apereo/cas/services/AbstractServicesManager.java | 2 ++ support/cas-server-support-saml-idp-core/build.gradle | 2 ++ .../idp/metadata/locator/AbstractSamlIdPMetadataLocator.java | 2 ++ 6 files changed, 10 insertions(+) diff --git a/core/cas-server-core-authentication-api/build.gradle b/core/cas-server-core-authentication-api/build.gradle index 326e6f717cf0..de653239640d 100644 --- a/core/cas-server-core-authentication-api/build.gradle +++ b/core/cas-server-core-authentication-api/build.gradle @@ -4,6 +4,7 @@ dependencies { api project(":api:cas-server-core-api-ticket") api project(":api:cas-server-core-api-authentication") api project(":api:cas-server-core-api-events") + api project(":api:cas-server-core-api-monitor") implementation project(":core:cas-server-core-configuration-api") implementation project(":core:cas-server-core-util-api") diff --git a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java index 9983060d14fa..6278df3c3eb2 100644 --- a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java +++ b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java @@ -3,6 +3,7 @@ import org.apereo.cas.authentication.principal.DefaultPrincipalFactory; import org.apereo.cas.authentication.principal.PrincipalFactory; import org.apereo.cas.configuration.model.core.authentication.AuthenticationHandlerStates; +import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.services.ServicesManager; import lombok.EqualsAndHashCode; @@ -23,6 +24,7 @@ @Getter @Setter @EqualsAndHashCode(of = {"name", "state", "order"}) +@Monitorable public abstract class AbstractAuthenticationHandler implements AuthenticationHandler { /** diff --git a/core/cas-server-core-services-registry/build.gradle b/core/cas-server-core-services-registry/build.gradle index aca649a36727..0f89b1ec3381 100644 --- a/core/cas-server-core-services-registry/build.gradle +++ b/core/cas-server-core-services-registry/build.gradle @@ -2,6 +2,7 @@ description = "Apereo CAS Core Services Registry and Manager" dependencies { api project(":api:cas-server-core-api-services") api project(":api:cas-server-core-api-events") + api project(":api:cas-server-core-api-monitor") implementation project(":core:cas-server-core-configuration-api") implementation project(":core:cas-server-core-web-api") diff --git a/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java b/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java index 87b3d8e71cb3..30f98eeb4442 100644 --- a/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java +++ b/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/AbstractServicesManager.java @@ -1,6 +1,7 @@ package org.apereo.cas.services; import org.apereo.cas.authentication.principal.Service; +import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.support.events.service.CasRegisteredServiceDeletedEvent; import org.apereo.cas.support.events.service.CasRegisteredServiceExpiredEvent; import org.apereo.cas.support.events.service.CasRegisteredServicePreDeleteEvent; @@ -38,6 +39,7 @@ @Slf4j @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @Getter +@Monitorable public abstract class AbstractServicesManager implements ServicesManager { /** diff --git a/support/cas-server-support-saml-idp-core/build.gradle b/support/cas-server-support-saml-idp-core/build.gradle index 60ed2a8722be..fb14980c10dd 100644 --- a/support/cas-server-support-saml-idp-core/build.gradle +++ b/support/cas-server-support-saml-idp-core/build.gradle @@ -2,6 +2,8 @@ description = "Apereo CAS SAML Identity Provider Core" dependencies { implementation libraries.shibutiljavasupport implementation libraries.pac4jcore + + api project(":api:cas-server-core-api-monitor") implementation project(":support:cas-server-support-saml-core") implementation project(":support:cas-server-support-saml-core-api") diff --git a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java index fde647680534..19bbb93cc8b4 100644 --- a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java +++ b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java @@ -1,5 +1,6 @@ package org.apereo.cas.support.saml.idp.metadata.locator; +import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.support.saml.services.SamlRegisteredService; import org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument; import org.apereo.cas.util.ResourceUtils; @@ -30,6 +31,7 @@ @Setter @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @Slf4j +@Monitorable public abstract class AbstractSamlIdPMetadataLocator implements SamlIdPMetadataLocator { private static final String CACHE_KEY_METADATA = "CasSamlIdentityProviderMetadata"; From c58bbc121e9d3074ff157a39c80a2288a793eccf Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 15 Mar 2023 12:46:04 +0400 Subject: [PATCH 010/266] remove starting "/" character from aws ssm config --- ...pleSystemsManagementCloudConfigBootstrapConfiguration.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/support/cas-server-support-configuration-cloud-aws-ssm/src/main/java/org/apereo/cas/config/AmazonSimpleSystemsManagementCloudConfigBootstrapConfiguration.java b/support/cas-server-support-configuration-cloud-aws-ssm/src/main/java/org/apereo/cas/config/AmazonSimpleSystemsManagementCloudConfigBootstrapConfiguration.java index b6535c07808e..0efbb7eed794 100644 --- a/support/cas-server-support-configuration-cloud-aws-ssm/src/main/java/org/apereo/cas/config/AmazonSimpleSystemsManagementCloudConfigBootstrapConfiguration.java +++ b/support/cas-server-support-configuration-cloud-aws-ssm/src/main/java/org/apereo/cas/config/AmazonSimpleSystemsManagementCloudConfigBootstrapConfiguration.java @@ -62,7 +62,9 @@ public PropertySource locate(final Environment environment) { LOGGER.trace("Fetched [{}] parameters with next token as [{}]", result.parameters().size(), result.nextToken()); result.parameters().forEach(p -> { - val key = StringUtils.removeEnd(StringUtils.removeStart(p.name(), prefix), "/"); + var propKey = StringUtils.removeStart(p.name(), prefix); + propKey = StringUtils.removeStart(propKey, "/"); + val key = StringUtils.removeEnd(propKey, "/"); props.put(key, p.value()); }); } while (nextToken != null); From f40491020d8c303d1611b010c9842ec33d25f2f3 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 15 Mar 2023 16:47:53 +0400 Subject: [PATCH 011/266] introduce api to handle observations with micrometer and spring boot --- .../cas/monitor/ExecutableObserver.java | 26 +++++++++ .../apereo/cas/monitor/MonitorableTask.java | 27 +++++++++ .../monitor/DefaultExecutableObserver.java | 55 +++++++++++++++++++ .../config/CasCoreMonitorConfiguration.java | 11 ++++ .../CasCoreMonitorConfigurationTests.java | 27 +++++++++ 5 files changed, 146 insertions(+) create mode 100644 api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java create mode 100644 api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java create mode 100644 core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java diff --git a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java new file mode 100644 index 000000000000..5efbe2bc75ee --- /dev/null +++ b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java @@ -0,0 +1,26 @@ +package org.apereo.cas.monitor; + +/** + * This is {@link ExecutableObserver}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +public interface ExecutableObserver { + /** + * Observe a task as a runnable. + * + * @param task the task + */ + void run(MonitorableTask task); + + /** + * Observe a task as a supplier. + * + * @param the type parameter + * @param task the task + * @param clazz the clazz + * @return the t + */ + T supply(MonitorableTask task, Class clazz); +} diff --git a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java new file mode 100644 index 000000000000..56ca27ddf0d5 --- /dev/null +++ b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java @@ -0,0 +1,27 @@ +package org.apereo.cas.monitor; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.With; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is {@link MonitorableTask}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@With +@Getter +@RequiredArgsConstructor +public class MonitorableTask { + private final Map boundedValues = new HashMap<>(); + + private final Map unboundedValues = new HashMap<>(); + + private final String name; + + private final Object executableTask; +} diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java new file mode 100644 index 000000000000..bcd226298002 --- /dev/null +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java @@ -0,0 +1,55 @@ +package org.apereo.cas.monitor; + +import io.micrometer.common.KeyValue; +import io.micrometer.common.KeyValues; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationRegistry; +import lombok.RequiredArgsConstructor; +import lombok.val; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.function.Supplier; + +/** + * This is {@link DefaultExecutableObserver}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@RequiredArgsConstructor +public class DefaultExecutableObserver implements ExecutableObserver { + private static final KeyValue[] EMPTY_KEYVALUES_ARRAY = {}; + + private final ObservationRegistry observationRegistry; + + @Override + public void run(final MonitorableTask task) { + prepareObservation(task).observe((Runnable) task.getExecutableTask()); + } + + @Override + public T supply(final MonitorableTask task, final Class clazz) { + return clazz.cast(prepareObservation(task) + .observe((Supplier) task.getExecutableTask())); + } + + protected Observation prepareObservation(final MonitorableTask task) { + val highCardinalityValues = toKeyValueArray(task.getUnboundedValues()); + val lowCardinalityValues = toKeyValueArray(task.getBoundedValues()); + return Observation.createNotStarted(task.getName(), observationRegistry) + .lowCardinalityKeyValues(KeyValues.of(lowCardinalityValues)) + .highCardinalityKeyValues(KeyValues.of(highCardinalityValues)) + .contextualName(task.getName()); + } + + private static KeyValue[] toKeyValueArray(final Map values) { + return values + .entrySet() + .stream() + .filter(entry -> StringUtils.isNotBlank(entry.getValue())) + .map(entry -> KeyValue.of(entry.getKey(), entry.getValue())) + .toList() + .toArray(EMPTY_KEYVALUES_ARRAY); + } +} diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java index c6dfef0a6c75..8ce4bc8f956d 100644 --- a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java @@ -2,12 +2,15 @@ import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.configuration.features.CasFeatureModule; +import org.apereo.cas.monitor.DefaultExecutableObserver; +import org.apereo.cas.monitor.ExecutableObserver; import org.apereo.cas.monitor.MemoryMonitorHealthIndicator; import org.apereo.cas.monitor.SystemMonitorHealthIndicator; import org.apereo.cas.monitor.TicketRegistryHealthIndicator; import org.apereo.cas.ticket.registry.TicketRegistry; import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; +import io.micrometer.observation.ObservationRegistry; import lombok.extern.slf4j.Slf4j; import lombok.val; import org.springframework.beans.factory.ObjectProvider; @@ -36,6 +39,14 @@ @ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Monitoring) @AutoConfiguration public class CasCoreMonitorConfiguration { + + @ConditionalOnMissingBean(name = "defaultExecutableObserver") + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + public ExecutableObserver defaultExecutableObserver(final ObservationRegistry observationRegistry) { + return new DefaultExecutableObserver(observationRegistry); + } + @ConditionalOnMissingBean(name = "memoryHealthIndicator") @Bean @ConditionalOnEnabledHealthIndicator("memoryHealthIndicator") diff --git a/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java b/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java index e7064e3553d1..22563edb66ca 100644 --- a/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java +++ b/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java @@ -13,6 +13,7 @@ import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.monitor.config.CasCoreMonitorConfiguration; +import lombok.val; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,12 +21,17 @@ import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + import static org.junit.jupiter.api.Assertions.*; /** @@ -36,6 +42,7 @@ */ @SpringBootTest(classes = { MetricsAutoConfiguration.class, + ObservationAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class, MetricsEndpointAutoConfiguration.class, RefreshAutoConfiguration.class, @@ -65,7 +72,12 @@ }) @EnableConfigurationProperties(CasConfigurationProperties.class) @Tag("Metrics") +@AutoConfigureObservability public class CasCoreMonitorConfigurationTests { + @Autowired + @Qualifier("defaultExecutableObserver") + private ExecutableObserver defaultExecutableObserver; + @Autowired @Qualifier("memoryHealthIndicator") private HealthIndicator memoryHealthIndicator; @@ -84,4 +96,19 @@ public void verifyOperation() { assertNotNull(sessionHealthIndicator); assertNotNull(systemHealthIndicator); } + + @Test + public void verifyObserabilitySupplier() { + val name = Thread.currentThread().getStackTrace()[1].getMethodName(); + val result = defaultExecutableObserver.supply(new MonitorableTask(name, (Supplier) () -> "CAS"), String.class); + assertEquals("CAS", result); + } + + @Test + public void verifyObserabilityRunner() { + val name = Thread.currentThread().getStackTrace()[1].getMethodName(); + val result = new AtomicBoolean(false); + defaultExecutableObserver.run(new MonitorableTask(name, (Runnable) () -> result.set(true))); + assertTrue(result.get()); + } } From 50f68024fbaddef8d2c0af2290c02dd570df1051 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 15 Mar 2023 16:56:16 +0400 Subject: [PATCH 012/266] introduce api to handle observations with micrometer and spring boot --- .../apereo/cas/monitor/ExecutableObserver.java | 15 +++++++++------ .../org/apereo/cas/monitor/MonitorableTask.java | 2 -- .../cas/monitor/DefaultExecutableObserver.java | 9 ++++----- .../config/CasCoreMonitorConfiguration.java | 2 ++ .../monitor/CasCoreMonitorConfigurationTests.java | 10 +++++----- .../apereo/cas/util/function/FunctionUtils.java | 7 +++++++ 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java index 5efbe2bc75ee..25166551f20e 100644 --- a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java +++ b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java @@ -1,5 +1,7 @@ package org.apereo.cas.monitor; +import java.util.function.Supplier; + /** * This is {@link ExecutableObserver}. * @@ -10,17 +12,18 @@ public interface ExecutableObserver { /** * Observe a task as a runnable. * - * @param task the task + * @param task the task + * @param runnable the runnable */ - void run(MonitorableTask task); + void run(MonitorableTask task, Runnable runnable); /** * Observe a task as a supplier. * - * @param the type parameter - * @param task the task - * @param clazz the clazz + * @param the type parameter + * @param task the task + * @param supplier the supplier * @return the t */ - T supply(MonitorableTask task, Class clazz); + T supply(MonitorableTask task, Supplier supplier); } diff --git a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java index 56ca27ddf0d5..ecc59014da55 100644 --- a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java +++ b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/MonitorableTask.java @@ -22,6 +22,4 @@ public class MonitorableTask { private final Map unboundedValues = new HashMap<>(); private final String name; - - private final Object executableTask; } diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java index bcd226298002..ed2a7855f0cd 100644 --- a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java @@ -24,14 +24,13 @@ public class DefaultExecutableObserver implements ExecutableObserver { private final ObservationRegistry observationRegistry; @Override - public void run(final MonitorableTask task) { - prepareObservation(task).observe((Runnable) task.getExecutableTask()); + public void run(final MonitorableTask task, final Runnable runnable) { + prepareObservation(task).observe(runnable); } @Override - public T supply(final MonitorableTask task, final Class clazz) { - return clazz.cast(prepareObservation(task) - .observe((Supplier) task.getExecutableTask())); + public T supply(final MonitorableTask task, final Supplier supplier) { + return prepareObservation(task).observe(supplier); } protected Observation prepareObservation(final MonitorableTask task) { diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java index 8ce4bc8f956d..1958668ba285 100644 --- a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.ScopedProxyMode; /** @@ -38,6 +39,7 @@ @Slf4j @ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Monitoring) @AutoConfiguration +@EnableAspectJAutoProxy(proxyTargetClass = false) public class CasCoreMonitorConfiguration { @ConditionalOnMissingBean(name = "defaultExecutableObserver") diff --git a/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java b/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java index 22563edb66ca..6f5395afe960 100644 --- a/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java +++ b/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java @@ -12,6 +12,7 @@ import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.monitor.config.CasCoreMonitorConfiguration; +import org.apereo.cas.util.function.FunctionUtils; import lombok.val; import org.junit.jupiter.api.Tag; @@ -30,7 +31,6 @@ import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; import static org.junit.jupiter.api.Assertions.*; @@ -99,16 +99,16 @@ public void verifyOperation() { @Test public void verifyObserabilitySupplier() { - val name = Thread.currentThread().getStackTrace()[1].getMethodName(); - val result = defaultExecutableObserver.supply(new MonitorableTask(name, (Supplier) () -> "CAS"), String.class); + val name = FunctionUtils.getMethodNameFromCurrentThead(); + val result = defaultExecutableObserver.supply(new MonitorableTask(name), () -> "CAS"); assertEquals("CAS", result); } @Test public void verifyObserabilityRunner() { - val name = Thread.currentThread().getStackTrace()[1].getMethodName(); + val name = FunctionUtils.getMethodNameFromCurrentThead(); val result = new AtomicBoolean(false); - defaultExecutableObserver.run(new MonitorableTask(name, (Runnable) () -> result.set(true))); + defaultExecutableObserver.run(new MonitorableTask(name), () -> result.set(true)); assertTrue(result.get()); } } diff --git a/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java b/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java index 62f56ba53f13..cbab587befd4 100644 --- a/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java +++ b/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java @@ -538,4 +538,11 @@ public static T doAndThrow(final CheckedSupplier supplier, throw handler.apply(e); } } + + /** + * Gets method name from current thead. + */ + public static String getMethodNameFromCurrentThead() { + return Thread.currentThread().getStackTrace()[1].getMethodName(); + } } From 229cb29f36279b92d655b32648467822acf591e2 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 16 Mar 2023 09:12:41 +0400 Subject: [PATCH 013/266] observe/monitor ticket registry observations via micrometer --- .../cas/monitor/ExecutableObserver.java | 6 +- .../build.gradle | 1 + .../monitor/DefaultExecutableObserver.java | 2 +- .../config/CasCoreMonitorConfiguration.java | 8 +++ .../CasCoreMonitorConfigurationTests.java | 11 ++-- core/cas-server-core-services/build.gradle | 1 + core/cas-server-core-tickets/build.gradle | 3 + ...CasCoreTicketsMonitoringConfiguration.java | 61 +++++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + ...reTicketsMonitoringConfigurationTests.java | 65 +++++++++++++++++++ .../registry/BaseTicketRegistryTests.java | 8 ++- .../cas/util/function/FunctionUtils.java | 7 -- .../release_notes/RC6.md | 12 +++- 13 files changed, 164 insertions(+), 22 deletions(-) create mode 100644 core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java create mode 100644 core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java diff --git a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java index 25166551f20e..23d71d122224 100644 --- a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java +++ b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java @@ -14,8 +14,9 @@ public interface ExecutableObserver { * * @param task the task * @param runnable the runnable + * @throws Throwable the throwable */ - void run(MonitorableTask task, Runnable runnable); + void run(MonitorableTask task, Runnable runnable) throws Throwable; /** * Observe a task as a supplier. @@ -24,6 +25,7 @@ public interface ExecutableObserver { * @param task the task * @param supplier the supplier * @return the t + * @throws Throwable the throwable */ - T supply(MonitorableTask task, Supplier supplier); + T supply(MonitorableTask task, Supplier supplier) throws Throwable; } diff --git a/core/cas-server-core-authentication/build.gradle b/core/cas-server-core-authentication/build.gradle index d8be8826b78a..444cef2b69b8 100644 --- a/core/cas-server-core-authentication/build.gradle +++ b/core/cas-server-core-authentication/build.gradle @@ -4,6 +4,7 @@ dependencies { api project(":api:cas-server-core-api-ticket") api project(":api:cas-server-core-api-authentication") api project(":api:cas-server-core-api-events") + api project(":api:cas-server-core-api-monitor") compileOnly project(":core:cas-server-core-services") diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java index ed2a7855f0cd..b44c0d5fbdc8 100644 --- a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/DefaultExecutableObserver.java @@ -29,7 +29,7 @@ public void run(final MonitorableTask task, final Runnable runnable) { } @Override - public T supply(final MonitorableTask task, final Supplier supplier) { + public T supply(final MonitorableTask task, final Supplier supplier) throws Throwable { return prepareObservation(task).observe(supplier); } diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java index 1958668ba285..076a7120efc1 100644 --- a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java @@ -10,7 +10,10 @@ import org.apereo.cas.ticket.registry.TicketRegistry; import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationHandler; import io.micrometer.observation.ObservationRegistry; +import io.micrometer.observation.ObservationTextPublisher; import lombok.extern.slf4j.Slf4j; import lombok.val; import org.springframework.beans.factory.ObjectProvider; @@ -49,6 +52,11 @@ public ExecutableObserver defaultExecutableObserver(final ObservationRegistry ob return new DefaultExecutableObserver(observationRegistry); } + @Bean + public ObservationHandler observationTextPublisher() { + return new ObservationTextPublisher(); + } + @ConditionalOnMissingBean(name = "memoryHealthIndicator") @Bean @ConditionalOnEnabledHealthIndicator("memoryHealthIndicator") diff --git a/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java b/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java index 6f5395afe960..cbdfa1cfa5fb 100644 --- a/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java +++ b/core/cas-server-core-monitor/src/test/java/org/apereo/cas/monitor/CasCoreMonitorConfigurationTests.java @@ -12,7 +12,6 @@ import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.monitor.config.CasCoreMonitorConfiguration; -import org.apereo.cas.util.function.FunctionUtils; import lombok.val; import org.junit.jupiter.api.Tag; @@ -98,17 +97,15 @@ public void verifyOperation() { } @Test - public void verifyObserabilitySupplier() { - val name = FunctionUtils.getMethodNameFromCurrentThead(); - val result = defaultExecutableObserver.supply(new MonitorableTask(name), () -> "CAS"); + public void verifyObserabilitySupplier() throws Throwable { + val result = defaultExecutableObserver.supply(new MonitorableTask("verifyObserabilitySupplier"), () -> "CAS"); assertEquals("CAS", result); } @Test - public void verifyObserabilityRunner() { - val name = FunctionUtils.getMethodNameFromCurrentThead(); + public void verifyObserabilityRunner() throws Throwable { val result = new AtomicBoolean(false); - defaultExecutableObserver.run(new MonitorableTask(name), () -> result.set(true)); + defaultExecutableObserver.run(new MonitorableTask("verifyObserabilityRunner"), () -> result.set(true)); assertTrue(result.get()); } } diff --git a/core/cas-server-core-services/build.gradle b/core/cas-server-core-services/build.gradle index a13395da6f6e..0ad5d33c63d9 100644 --- a/core/cas-server-core-services/build.gradle +++ b/core/cas-server-core-services/build.gradle @@ -2,6 +2,7 @@ description = "Apereo CAS Core Services" dependencies { api project(":api:cas-server-core-api-services") api project(":api:cas-server-core-api-audit") + api project(":api:cas-server-core-api-monitor") implementation project(":core:cas-server-core-services-api") implementation project(":core:cas-server-core-services-registry") diff --git a/core/cas-server-core-tickets/build.gradle b/core/cas-server-core-tickets/build.gradle index df72d5c5ebbd..ec5a55c7935a 100644 --- a/core/cas-server-core-tickets/build.gradle +++ b/core/cas-server-core-tickets/build.gradle @@ -1,6 +1,8 @@ description = "Apereo CAS Core Tickets" dependencies { api project(":api:cas-server-core-api-ticket") + api project(":api:cas-server-core-api-monitor") + api project(":core:cas-server-core-tickets-api") implementation project(":core:cas-server-core-services-api") @@ -24,6 +26,7 @@ dependencies { testImplementation project(":core:cas-server-core") testImplementation project(":core:cas-server-core-notifications") testImplementation project(":core:cas-server-core-logout-api") + testImplementation project(":core:cas-server-core-monitor") testImplementation project(":support:cas-server-support-person-directory") diff --git a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java new file mode 100644 index 000000000000..18d0cea3571b --- /dev/null +++ b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java @@ -0,0 +1,61 @@ +package org.apereo.cas.config; + +import org.apereo.cas.configuration.CasConfigurationProperties; +import org.apereo.cas.configuration.features.CasFeatureModule; +import org.apereo.cas.monitor.ExecutableObserver; +import org.apereo.cas.monitor.MonitorableTask; +import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; + +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.jooq.lambda.Unchecked; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; + +/** + * This is {@link CasCoreTicketsMonitoringConfiguration}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@EnableConfigurationProperties(CasConfigurationProperties.class) +@Slf4j +@ConditionalOnFeatureEnabled(feature = { + CasFeatureModule.FeatureCatalog.Monitoring, + CasFeatureModule.FeatureCatalog.TicketRegistry +}) +@AutoConfiguration +public class CasCoreTicketsMonitoringConfiguration { + + @Bean + @ConditionalOnMissingBean(name = "ticketRegistryMonitoringAspect") + public TicketRegistryMonitoringAspect ticketRegistryMonitoringAspect(final ExecutableObserver observer) { + return new TicketRegistryMonitoringAspect(observer); + } + + @Aspect + @Slf4j + @SuppressWarnings("UnusedMethod") + record TicketRegistryMonitoringAspect(ExecutableObserver observer) { + @Around("allComponentsInTicketRegistryNamespace()") + public Object aroundAdvice(final ProceedingJoinPoint joinPoint) throws Throwable { + val taskName = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName(); + val task = new MonitorableTask(taskName); + return observer.supply(task, Unchecked.supplier(() -> { + var args = joinPoint.getArgs(); + LOGGER.trace("Executing [{}]", joinPoint.getStaticPart().toLongString()); + return joinPoint.proceed(args); + })); + } + + @Pointcut("within(org.apereo.cas.ticket.registry.*)") + private void allComponentsInTicketRegistryNamespace() { + } + } +} diff --git a/core/cas-server-core-tickets/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/core/cas-server-core-tickets/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 48568d164f53..c544d459f6db 100644 --- a/core/cas-server-core-tickets/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/core/cas-server-core-tickets/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -5,3 +5,4 @@ org.apereo.cas.config.CasCoreTicketsConfiguration org.apereo.cas.config.CasCoreTicketsSchedulingConfiguration org.apereo.cas.config.CasCoreTicketComponentSerializationConfiguration org.apereo.cas.config.CasCoreTicketsSerializationConfiguration +org.apereo.cas.config.CasCoreTicketsMonitoringConfiguration diff --git a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java new file mode 100644 index 000000000000..6bc3a6299211 --- /dev/null +++ b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java @@ -0,0 +1,65 @@ +package org.apereo.cas.ticket.monitoring; + +import org.apereo.cas.config.CasCoreTicketsMonitoringConfiguration; +import org.apereo.cas.mock.MockTicketGrantingTicket; +import org.apereo.cas.monitor.config.CasCoreMonitorConfiguration; +import org.apereo.cas.ticket.registry.BaseTicketRegistryTests; +import org.apereo.cas.ticket.registry.TicketRegistry; + +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationHandler; +import io.micrometer.observation.ObservationTextPublisher; +import lombok.val; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * This is {@link CasCoreTicketsMonitoringConfigurationTests}. + * + * @author Misagh Moayyed + * @since 7.0.0 + */ +@SpringBootTest(classes = { + CasCoreTicketsMonitoringConfigurationTests.CasCoreTicketsMonitoringTestConfiguration.class, + CasCoreMonitorConfiguration.class, + CasCoreTicketsMonitoringConfiguration.class, + BaseTicketRegistryTests.SharedTestConfiguration.class +}) +@Tag("Tickets") +@EnableAspectJAutoProxy(proxyTargetClass = false) +@AutoConfigureObservability +public class CasCoreTicketsMonitoringConfigurationTests { + @Autowired + @Qualifier(TicketRegistry.BEAN_NAME) + private TicketRegistry ticketRegistry; + + private static final List ENTRIES = new ArrayList<>(); + + @Test + public void verifyOperation() throws Exception { + ticketRegistry.addTicket(new MockTicketGrantingTicket("casuser")); + val tickets = ticketRegistry.getTickets(); + assertFalse(tickets.isEmpty()); + assertFalse(ENTRIES.isEmpty()); + } + + @TestConfiguration(proxyBeanMethods = false) + static class CasCoreTicketsMonitoringTestConfiguration { + @Bean + public ObservationHandler collectingObservationHandler() { + return new ObservationTextPublisher(ENTRIES::add); + } + } +} diff --git a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/BaseTicketRegistryTests.java b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/BaseTicketRegistryTests.java index 13f8daec75ac..5a1da4539ee5 100644 --- a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/BaseTicketRegistryTests.java +++ b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/registry/BaseTicketRegistryTests.java @@ -68,6 +68,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; @@ -642,7 +643,10 @@ private void setUpEncryption() { } } - @ImportAutoConfiguration(RefreshAutoConfiguration.class) + @ImportAutoConfiguration({ + ObservationAutoConfiguration.class, + RefreshAutoConfiguration.class + }) @SpringBootConfiguration @Import({ CasCoreHttpConfiguration.class, @@ -669,6 +673,6 @@ private void setUpEncryption() { CasCoreNotificationsConfiguration.class, CasWebApplicationServiceFactoryConfiguration.class }) - static class SharedTestConfiguration { + public static class SharedTestConfiguration { } } diff --git a/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java b/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java index cbab587befd4..62f56ba53f13 100644 --- a/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java +++ b/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/function/FunctionUtils.java @@ -538,11 +538,4 @@ public static T doAndThrow(final CheckedSupplier supplier, throw handler.apply(e); } } - - /** - * Gets method name from current thead. - */ - public static String getMethodNameFromCurrentThead() { - return Thread.currentThread().getStackTrace()[1].getMethodName(); - } } diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index cb5ccb928cd9..0c1a68c26e04 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -46,12 +46,18 @@ The following items are new improvements and enhancements presented in this rele A new ticket registry implementation backed by [Google Cloud's PubSub](../ticketing/GCP-PubSub-Ticket-Registry.html) is now available. ## Other Stuff - - + +- Supported grant types and response types are recognized during [OpenID Connect Dynamic Registration](../authentication/OIDC-Authentication-Dynamic-Registration.html). +- Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io/docs/observation) and then reported as metrics. ## Library Upgrades - + +- Spring +- Spring Integration +- Netty +- Logback - Ldaptive - Twillio +- jQuery - Amazon SDK - Spring Boot From 38138d48bc67bad3fa7b3f7465097fd393a1f5d3 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 16 Mar 2023 09:13:04 +0400 Subject: [PATCH 014/266] bump tomcat max-threads to 400 --- gradle.properties | 10 +++++----- .../src/main/resources/application.properties | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8a92d0bada9d..6e980467531f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -84,7 +84,7 @@ jaxbImplVersion=4.0.1 # Swagger versions ############################### swaggerVersion=2.2.8 -springDocVersion=2.0.3 +springDocVersion=2.0.4 ############################### # Logging versions ############################### @@ -94,7 +94,7 @@ inspektrVersion=2.0.1 sentryRavenVersion=8.0.3 splunkLoggingVersion=1.11.7 log4jVersion=2.20.0 -logbackVersion=1.4.5 +logbackVersion=1.4.6 fluentdVersion=0.3.4 fluentdLog4jVersion=1.0.0 ############################### @@ -251,7 +251,7 @@ acmeClientVersion=2.16 ############################### # Metrics versions ############################### -micrometerVersion=1.10.4 +micrometerVersion=1.10.5 dropwizardVersion=4.2.17 ############################### # Spring Session versions @@ -321,7 +321,7 @@ firebaseAdminVersion=9.1.1 ############################### ldaptiveVersion=2.1.2 unboundidVersion=6.0.8 -nettyVersion=4.1.89.Final +nettyVersion=4.1.90.Final ############################### # SPNEGO versions ############################### @@ -422,7 +422,7 @@ ektorpVersion=1.5.0 ############################### webjarLocatorVersion=0.52 halVersion=1.2.0 -jqueryVersion=3.6.3 +jqueryVersion=3.6.4 highlightJsVersion=11.5.0 zxcvbnVersion=4.4.2 bootstrapVersion=5.2.3 diff --git a/webapp/cas-server-webapp-resources/src/main/resources/application.properties b/webapp/cas-server-webapp-resources/src/main/resources/application.properties index fdcc0143aca8..8cbc2962ecf7 100644 --- a/webapp/cas-server-webapp-resources/src/main/resources/application.properties +++ b/webapp/cas-server-webapp-resources/src/main/resources/application.properties @@ -32,7 +32,7 @@ server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms) server.tomcat.accesslog.suffix=.log server.tomcat.background-processor-delay=0s server.tomcat.threads.min-spare=10 -server.tomcat.threads.max=200 +server.tomcat.threads.max=400 server.tomcat.remoteip.port-header=X-Forwarded-Port server.tomcat.remoteip.protocol-header=X-Forwarded-Proto From f5080d33865a6958f64e148db5a5ba92ec4f6ec1 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 16 Mar 2023 09:13:25 +0400 Subject: [PATCH 015/266] ensure response/grant types are recognized during oidc dynamic registration flow --- .../dynareg/OidcClientRegistrationRequestTranslator.java | 7 +++++-- .../dynareg/OidcInitialAccessTokenController.java | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java index aae71f7b2fec..96e7a2814d3e 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java @@ -123,11 +123,14 @@ public OidcRegisteredService translate( FunctionUtils.doIfNotBlank(registrationRequest.getLogo(), __ -> registeredService.setLogo(registrationRequest.getLogo())); - FunctionUtils.doIfNotBlank(registrationRequest.getPolicyUri(), __ -> registeredService.setInformationUrl(registrationRequest.getPolicyUri())); - FunctionUtils.doIfNotBlank(registrationRequest.getTermsOfUseUri(), __ -> registeredService.setPrivacyUrl(registrationRequest.getTermsOfUseUri())); + FunctionUtils.doIfNotNull(registrationRequest.getGrantTypes(), + __ -> registeredService.setSupportedGrantTypes(new HashSet<>(registrationRequest.getGrantTypes()))); + FunctionUtils.doIfNotNull(registrationRequest.getResponseTypes(), + __ -> registeredService.setSupportedResponseTypes(new HashSet<>(registrationRequest.getResponseTypes()))); + if (!StringUtils.equalsIgnoreCase("none", registrationRequest.getUserInfoSignedReponseAlg())) { registeredService.setUserInfoSigningAlg(registrationRequest.getUserInfoSignedReponseAlg()); } diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcInitialAccessTokenController.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcInitialAccessTokenController.java index ab15f9aaeb0a..601e97ed05bd 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcInitialAccessTokenController.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcInitialAccessTokenController.java @@ -120,8 +120,7 @@ public ModelAndView handleRequestInternal( .service(service) .grantType(OAuth20GrantTypes.NONE) .responseType(OAuth20ResponseTypes.NONE) - .scopes(Set.of(OidcConstants.StandardScopes.OPENID.getScope(), - OidcConstants.CLIENT_REGISTRATION_SCOPE)) + .scopes(Set.of(OidcConstants.StandardScopes.OPENID.getScope(), OidcConstants.CLIENT_REGISTRATION_SCOPE)) .build(); return generateInitialAccessToken(holder) .map(accessToken -> { From 0ba741cbac47917ef7d601a943d9ea49c05c3329 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 16 Mar 2023 09:14:06 +0400 Subject: [PATCH 016/266] minor build fixes --- .../CasCoreTicketsMonitoringConfigurationTests.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java index 6bc3a6299211..688584dd9f7d 100644 --- a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java +++ b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/ticket/monitoring/CasCoreTicketsMonitoringConfigurationTests.java @@ -41,11 +41,12 @@ @EnableAspectJAutoProxy(proxyTargetClass = false) @AutoConfigureObservability public class CasCoreTicketsMonitoringConfigurationTests { + private static final List ENTRIES = new ArrayList<>(); + @Autowired @Qualifier(TicketRegistry.BEAN_NAME) private TicketRegistry ticketRegistry; - - private static final List ENTRIES = new ArrayList<>(); + @Test public void verifyOperation() throws Exception { From 25b1b50b5312f72ac63a8936f07c0eb48b15f8ac Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 16 Mar 2023 10:15:55 +0400 Subject: [PATCH 017/266] observe/monitor ticket registry observations via micrometer --- api/cas-server-core-api-authentication/build.gradle | 1 + .../org/apereo/cas/authentication/AuthenticationHandler.java | 2 ++ .../org/apereo/cas/authentication/AuthenticationManager.java | 3 +++ api/cas-server-core-api-ticket/build.gradle | 1 + .../java/org/apereo/cas/ticket/registry/TicketRegistry.java | 2 ++ .../cas/authentication/AbstractAuthenticationHandler.java | 2 -- .../apereo/cas/ticket/registry/AbstractTicketRegistry.java | 2 -- .../org/apereo/cas/config/CasJavaMelodyConfiguration.java | 4 ++-- .../idp/metadata/locator/AbstractSamlIdPMetadataLocator.java | 2 -- .../saml/idp/metadata/locator/SamlIdPMetadataLocator.java | 2 ++ .../cache/SamlRegisteredServiceCachingMetadataResolver.java | 2 ++ 11 files changed, 15 insertions(+), 8 deletions(-) diff --git a/api/cas-server-core-api-authentication/build.gradle b/api/cas-server-core-api-authentication/build.gradle index 45e9ca310f58..ab22987c3639 100644 --- a/api/cas-server-core-api-authentication/build.gradle +++ b/api/cas-server-core-api-authentication/build.gradle @@ -1,5 +1,6 @@ description = "Apereo CAS Core Authentication APIs" dependencies { api project(":api:cas-server-core-api-protocol") + api project(":api:cas-server-core-api-monitor") api project(":api:cas-server-core-api-configuration-model") } diff --git a/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationHandler.java b/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationHandler.java index 3e37a656ee26..2c570216d1ec 100644 --- a/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationHandler.java +++ b/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationHandler.java @@ -3,6 +3,7 @@ import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.configuration.model.core.authentication.AuthenticationHandlerStates; +import org.apereo.cas.monitor.Monitorable; import org.springframework.core.Ordered; @@ -16,6 +17,7 @@ * @since 4.0.0 */ @FunctionalInterface +@Monitorable public interface AuthenticationHandler extends Ordered { /** diff --git a/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationManager.java b/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationManager.java index 34b576dcdb41..11d83459ef15 100644 --- a/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationManager.java +++ b/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationManager.java @@ -1,5 +1,7 @@ package org.apereo.cas.authentication; +import org.apereo.cas.monitor.Monitorable; + /** * Authenticates one or more credentials. * @@ -8,6 +10,7 @@ * @since 3.0.0 */ @FunctionalInterface +@Monitorable public interface AuthenticationManager { /** diff --git a/api/cas-server-core-api-ticket/build.gradle b/api/cas-server-core-api-ticket/build.gradle index 1d8c75182d90..36c93d452bfd 100644 --- a/api/cas-server-core-api-ticket/build.gradle +++ b/api/cas-server-core-api-ticket/build.gradle @@ -2,5 +2,6 @@ description = "Apereo CAS Core Ticket APIs" dependencies { api project(":api:cas-server-core-api-authentication") api project(":api:cas-server-core-api-util") + api project(":api:cas-server-core-api-monitor") } diff --git a/api/cas-server-core-api-ticket/src/main/java/org/apereo/cas/ticket/registry/TicketRegistry.java b/api/cas-server-core-api-ticket/src/main/java/org/apereo/cas/ticket/registry/TicketRegistry.java index b8d9460722b8..5c817958fc03 100644 --- a/api/cas-server-core-api-ticket/src/main/java/org/apereo/cas/ticket/registry/TicketRegistry.java +++ b/api/cas-server-core-api-ticket/src/main/java/org/apereo/cas/ticket/registry/TicketRegistry.java @@ -1,5 +1,6 @@ package org.apereo.cas.ticket.registry; +import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.ticket.AuthenticationAwareTicket; import org.apereo.cas.ticket.Ticket; import org.apereo.cas.ticket.TicketGrantingTicket; @@ -22,6 +23,7 @@ * @author Scott Battaglia * @since 3.0.0 */ +@Monitorable public interface TicketRegistry { /** diff --git a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java index 6278df3c3eb2..9983060d14fa 100644 --- a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java +++ b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AbstractAuthenticationHandler.java @@ -3,7 +3,6 @@ import org.apereo.cas.authentication.principal.DefaultPrincipalFactory; import org.apereo.cas.authentication.principal.PrincipalFactory; import org.apereo.cas.configuration.model.core.authentication.AuthenticationHandlerStates; -import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.services.ServicesManager; import lombok.EqualsAndHashCode; @@ -24,7 +23,6 @@ @Getter @Setter @EqualsAndHashCode(of = {"name", "state", "order"}) -@Monitorable public abstract class AbstractAuthenticationHandler implements AuthenticationHandler { /** diff --git a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java index ae1fc2511741..54a2db9d2ab0 100644 --- a/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java +++ b/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java @@ -1,7 +1,6 @@ package org.apereo.cas.ticket.registry; import org.apereo.cas.authentication.CoreAuthenticationUtils; -import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.ticket.AuthenticatedServicesAwareTicketGrantingTicket; import org.apereo.cas.ticket.AuthenticationAwareTicket; import org.apereo.cas.ticket.EncodedTicket; @@ -46,7 +45,6 @@ */ @Slf4j @AllArgsConstructor -@Monitorable public abstract class AbstractTicketRegistry implements TicketRegistry { private static final String MESSAGE = "Ticket encryption is not enabled. Falling back to default behavior"; diff --git a/support/cas-server-support-javamelody/src/main/java/org/apereo/cas/config/CasJavaMelodyConfiguration.java b/support/cas-server-support-javamelody/src/main/java/org/apereo/cas/config/CasJavaMelodyConfiguration.java index 8471444721be..a82cda113559 100644 --- a/support/cas-server-support-javamelody/src/main/java/org/apereo/cas/config/CasJavaMelodyConfiguration.java +++ b/support/cas-server-support-javamelody/src/main/java/org/apereo/cas/config/CasJavaMelodyConfiguration.java @@ -34,8 +34,8 @@ public class CasJavaMelodyConfiguration { @Bean - @ConditionalOnMissingBean(name = "monitoringTicketRegistryAdvisor") - public MonitoringSpringAdvisor monitoringTicketRegistryAdvisor() { + @ConditionalOnMissingBean(name = "monitorableComponentsAdvisor") + public MonitoringSpringAdvisor monitorableComponentsAdvisor() { return new MonitoringSpringAdvisor(new AnnotationMatchingPointcut(Monitorable.class, null)); } diff --git a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java index 19bbb93cc8b4..fde647680534 100644 --- a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java +++ b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/AbstractSamlIdPMetadataLocator.java @@ -1,6 +1,5 @@ package org.apereo.cas.support.saml.idp.metadata.locator; -import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.support.saml.services.SamlRegisteredService; import org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument; import org.apereo.cas.util.ResourceUtils; @@ -31,7 +30,6 @@ @Setter @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @Slf4j -@Monitorable public abstract class AbstractSamlIdPMetadataLocator implements SamlIdPMetadataLocator { private static final String CACHE_KEY_METADATA = "CasSamlIdentityProviderMetadata"; diff --git a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/SamlIdPMetadataLocator.java b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/SamlIdPMetadataLocator.java index 1c07e06ae593..4406830cbc9d 100644 --- a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/SamlIdPMetadataLocator.java +++ b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/idp/metadata/locator/SamlIdPMetadataLocator.java @@ -1,5 +1,6 @@ package org.apereo.cas.support.saml.idp.metadata.locator; +import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.support.saml.SamlIdPUtils; import org.apereo.cas.support.saml.services.SamlRegisteredService; import org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument; @@ -14,6 +15,7 @@ * @author Misagh Moayyed * @since 5.3.0 */ +@Monitorable public interface SamlIdPMetadataLocator { /** * Gets full location of signing cert file. diff --git a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/SamlRegisteredServiceCachingMetadataResolver.java b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/SamlRegisteredServiceCachingMetadataResolver.java index 8395c6def1a9..707ef8e69015 100644 --- a/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/SamlRegisteredServiceCachingMetadataResolver.java +++ b/support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/SamlRegisteredServiceCachingMetadataResolver.java @@ -1,5 +1,6 @@ package org.apereo.cas.support.saml.services.idp.metadata.cache; +import org.apereo.cas.monitor.Monitorable; import org.apereo.cas.support.saml.OpenSamlConfigBean; import org.apereo.cas.support.saml.services.SamlRegisteredService; @@ -16,6 +17,7 @@ * @author Misagh Moayyed * @since 5.0.0 */ +@Monitorable public interface SamlRegisteredServiceCachingMetadataResolver { /** From 567285ff8dc47b4f709d8d2f715505b2864745e7 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 16 Mar 2023 10:41:09 +0400 Subject: [PATCH 018/266] organize services by type, optionally, for JSON/YAML files --- .../AbstractResourceBasedServiceRegistry.java | 32 ++++++++++++------- .../release_notes/RC6.md | 1 + .../services/JSON-Service-Management.md | 15 +++++++++ .../services/YAML-Service-Management.md | 22 +++++++++++-- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java b/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java index 2e472291833c..d52a7573dc72 100644 --- a/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java +++ b/core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java @@ -41,6 +41,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -174,7 +175,7 @@ public RegisteredService save(final RegisteredService service) { val fileName = getRegisteredServiceFileName(service); try (val out = Files.newOutputStream(fileName.toPath())) { invokeServiceRegistryListenerPreSave(service); - val result = this.registeredServiceSerializers.stream().anyMatch(s -> { + val result = registeredServiceSerializers.stream().anyMatch(s -> { try { s.to(out, service); return true; @@ -189,7 +190,7 @@ public RegisteredService save(final RegisteredService service) { if (this.services.containsKey(service.getId())) { LOGGER.debug("Found existing service definition by id [{}]. Saving...", service.getId()); } - this.services.put(service.getId(), service); + services.put(service.getId(), service); LOGGER.debug("Saved service to [{}]", fileName.getCanonicalPath()); } catch (final IOException e) { throw new IllegalArgumentException("IO error opening file stream.", e); @@ -362,21 +363,30 @@ protected RegisteredService getRegisteredServiceFromFile(final File file) { return null; } - /** - * Creates a file for a registered service. - * The file is named as {@code [SERVICE-NAME]-[SERVICE-ID]-.{@value #getExtensions()}} - * - * @param service Registered service. - * @return file in service registry directory. - * @throws IllegalArgumentException if file name is invalid - */ protected File getRegisteredServiceFileName(final RegisteredService service) { val fileName = resourceNamingStrategy.build(service, getExtensions()[0]); - val svcFile = new File(this.serviceRegistryDirectory.toFile(), fileName); + + val parentDirectory = determineParentDirectoryFor(service); + val svcFile = new File(parentDirectory, fileName); LOGGER.debug("Using [{}] as the service definition file", svcFile.getAbsolutePath()); return svcFile; } + private File determineParentDirectoryFor(final RegisteredService service) { + val defaultServicesDirectory = serviceRegistryDirectory.toFile(); + + val friendlyName = service.getFriendlyName(); + val candidateParentDirectories = List.of( + new File(defaultServicesDirectory, friendlyName.toLowerCase().replace(" ", "-")), + new File(defaultServicesDirectory, friendlyName) + ); + return candidateParentDirectories + .stream() + .filter(dir -> dir.exists() && dir.isDirectory()) + .findFirst() + .orElse(defaultServicesDirectory); + } + /** * Gets extension associated with files in the given resource directory. * diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index 0c1a68c26e04..046be9372584 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -49,6 +49,7 @@ A new ticket registry implementation backed by [Google Cloud's PubSub](../ticket - Supported grant types and response types are recognized during [OpenID Connect Dynamic Registration](../authentication/OIDC-Authentication-Dynamic-Registration.html). - Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io/docs/observation) and then reported as metrics. +- JSON and YAML service registries are able to auto-organize and store service definition files in dedicated directories identified by the service type. ## Library Upgrades diff --git a/docs/cas-server-documentation/services/JSON-Service-Management.md b/docs/cas-server-documentation/services/JSON-Service-Management.md index 7ba44043fd9f..7ed7fca43731 100644 --- a/docs/cas-server-documentation/services/JSON-Service-Management.md +++ b/docs/cas-server-documentation/services/JSON-Service-Management.md @@ -44,6 +44,8 @@ Please make sure all field values in the JSON blob are correctly escaped, specia regular expression, certain regex constructs such as "." and "\d" need to be doubly escaped.

+## Naming Conventions + The naming convention for new JSON files is recommended to be the following: ```bash @@ -54,6 +56,19 @@ Based on the above formula, for example the above JSON snippet shall be named: ` that because files are created based on the `serviceName`, you will need to make sure [characters considered invalid for file names](https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words) are not used as part of the name. Furthermore, note that CAS **MUST** be given full read/write permissions on directory which contains service definition files. + +The registry is able to auto-organize service definition files into dedicated directories based on the service type. If any of the following +subdirectories exist inside the base services directory for a CAS service, CAS would auto-choose the appropriate directory by type: + +| Service Type | Subdirectories | +|----------------|----------------------------------------------------------------| +| CAS | `CAS Client`, `cas-client` | +| OpenID Connect | `OpenID Connect Relying Party`, `openid-connect-relying-party` | +| OAuth2 | `OAuth2 Client`, `oauth2-client` | +| SAML2 | `SAML2 Service Provider`, `saml2-service-provider` | +| WS-Federation | `WS Federation Relying Party`, `ws-federation-relying-party` | + +If no subdirectory for a service type is found, the base services directory would be used.
:warning: Duplicate Services

As you add more files to the directory, you need to be absolutely sure that no two service definitions diff --git a/docs/cas-server-documentation/services/YAML-Service-Management.md b/docs/cas-server-documentation/services/YAML-Service-Management.md index a9249095d648..3550315afc36 100644 --- a/docs/cas-server-documentation/services/YAML-Service-Management.md +++ b/docs/cas-server-documentation/services/YAML-Service-Management.md @@ -34,7 +34,8 @@ accessStrategy: !:warning: YAML Validation

-The tags containing classname hints (!<classname>) cause problems with many YAML validators. If you need to validate your YAML, try removing those tags for validation. Remember that an empty map ({}) may be required after the tag if you are not including any attributes for a property. +The tags containing classname hints (!<classname>) cause problems with many YAML validators. If +you need to validate your YAML, try removing those tags for validation. Remember that an empty map ({}) may be required after the tag if you are not including any attributes for a property.

:warning: Clustering Services

@@ -51,13 +52,30 @@ Please make sure all field values in the blob are correctly escaped, specially f

+## Naming Conventions + The naming convention for new files is recommended to be the following: ```bash YAML fileName = serviceName + "-" + serviceNumericId + ".yml" ``` -Remember that because files are created based on the `serviceName`, you will need to make sure [characters considered invalid for file names](https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words) are not used as part of the name. Furthermore, note that CAS **MUST** be given full read/write permissions on directory which contains service definition files. +Remember that because files are created based on the `serviceName`, you will need to +make sure [characters considered invalid for file names](https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words) +are not used as part of the name. Furthermore, note that CAS **MUST** be given full read/write permissions on directory which contains service definition files. + +The registry is able to auto-organize service definition files into dedicated directories based on the service type. If any of the following +subdirectories exist inside the base services directory for a CAS service, CAS would auto-choose the appropriate directory by type: + +| Service Type | Subdirectories | +|----------------|----------------------------------------------------------------| +| CAS | `CAS Client`, `cas-client` | +| OpenID Connect | `OpenID Connect Relying Party`, `openid-connect-relying-party` | +| OAuth2 | `OAuth2 Client`, `oauth2-client` | +| SAML2 | `SAML2 Service Provider`, `saml2-service-provider` | +| WS-Federation | `WS Federation Relying Party`, `ws-federation-relying-party` | + +If no subdirectory for a service type is found, the base services directory would be used.
:warning: Duplicate Services

As you add more files to the directory, you need to be absolutely sure that no two service definitions From c33a385e7a0f7e122b816e4ac6b17d5ac5994e11 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 08:37:39 +0400 Subject: [PATCH 019/266] minor build fixes --- .../cas/monitor/ExecutableObserver.java | 4 +++ .../config/CasCoreMonitorConfiguration.java | 2 +- ...CasCoreTicketsMonitoringConfiguration.java | 28 ++++++++++++++----- .../java/org/apereo/cas/AllTestsSuite.java | 2 ++ .../Configuring-SAML-SP-Integrations.md | 2 +- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java index 23d71d122224..13e1e024e127 100644 --- a/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java +++ b/api/cas-server-core-api-monitor/src/main/java/org/apereo/cas/monitor/ExecutableObserver.java @@ -9,6 +9,10 @@ * @since 7.0.0 */ public interface ExecutableObserver { + /** + * Bean name. + */ + String BEAN_NAME = "defaultExecutableObserver"; /** * Observe a task as a runnable. * diff --git a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java index 076a7120efc1..35e7d8fef89e 100644 --- a/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java +++ b/core/cas-server-core-monitor/src/main/java/org/apereo/cas/monitor/config/CasCoreMonitorConfiguration.java @@ -45,7 +45,7 @@ @EnableAspectJAutoProxy(proxyTargetClass = false) public class CasCoreMonitorConfiguration { - @ConditionalOnMissingBean(name = "defaultExecutableObserver") + @ConditionalOnMissingBean(name = ExecutableObserver.BEAN_NAME) @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public ExecutableObserver defaultExecutableObserver(final ObservationRegistry observationRegistry) { diff --git a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java index 18d0cea3571b..7f8ef129db5e 100644 --- a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java +++ b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java @@ -4,6 +4,7 @@ import org.apereo.cas.configuration.features.CasFeatureModule; import org.apereo.cas.monitor.ExecutableObserver; import org.apereo.cas.monitor.MonitorableTask; +import org.apereo.cas.util.function.FunctionUtils; import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; import lombok.extern.slf4j.Slf4j; @@ -13,7 +14,9 @@ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.jooq.lambda.Unchecked; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -30,28 +33,39 @@ CasFeatureModule.FeatureCatalog.Monitoring, CasFeatureModule.FeatureCatalog.TicketRegistry }) +@ConditionalOnBean(name = ExecutableObserver.BEAN_NAME) @AutoConfiguration public class CasCoreTicketsMonitoringConfiguration { @Bean @ConditionalOnMissingBean(name = "ticketRegistryMonitoringAspect") - public TicketRegistryMonitoringAspect ticketRegistryMonitoringAspect(final ExecutableObserver observer) { + public TicketRegistryMonitoringAspect ticketRegistryMonitoringAspect(final ObjectProvider observer) { return new TicketRegistryMonitoringAspect(observer); } @Aspect @Slf4j @SuppressWarnings("UnusedMethod") - record TicketRegistryMonitoringAspect(ExecutableObserver observer) { + record TicketRegistryMonitoringAspect(ObjectProvider observerProvider) { @Around("allComponentsInTicketRegistryNamespace()") - public Object aroundAdvice(final ProceedingJoinPoint joinPoint) throws Throwable { - val taskName = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName(); - val task = new MonitorableTask(taskName); - return observer.supply(task, Unchecked.supplier(() -> { + public Object aroundTicketRegistryOperations(final ProceedingJoinPoint joinPoint) { + return observerProvider + .stream() + .map(Unchecked.function(observer -> { + val taskName = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName(); + val task = new MonitorableTask(taskName); + return observer.supply(task, () -> executeJoinpoint(joinPoint)); + })) + .findFirst() + .orElseGet(() -> executeJoinpoint(joinPoint)); + } + + private static Object executeJoinpoint(final ProceedingJoinPoint joinPoint) { + return FunctionUtils.doUnchecked(() -> { var args = joinPoint.getArgs(); LOGGER.trace("Executing [{}]", joinPoint.getStaticPart().toLongString()); return joinPoint.proceed(args); - })); + }); } @Pointcut("within(org.apereo.cas.ticket.registry.*)") diff --git a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/AllTestsSuite.java b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/AllTestsSuite.java index e8f3a113067c..ef78e1e1d50e 100644 --- a/core/cas-server-core-tickets/src/test/java/org/apereo/cas/AllTestsSuite.java +++ b/core/cas-server-core-tickets/src/test/java/org/apereo/cas/AllTestsSuite.java @@ -26,6 +26,7 @@ import org.apereo.cas.ticket.factory.DefaultServiceTicketFactoryTests; import org.apereo.cas.ticket.factory.DefaultTicketGrantingTicketFactoryTests; import org.apereo.cas.ticket.factory.DefaultTransientSessionTicketFactoryTests; +import org.apereo.cas.ticket.monitoring.CasCoreTicketsMonitoringConfigurationTests; import org.apereo.cas.ticket.proxy.support.Cas10ProxyHandlerTests; import org.apereo.cas.ticket.proxy.support.Cas20ProxyHandlerTests; import org.apereo.cas.ticket.registry.CachingTicketRegistryTests; @@ -67,6 +68,7 @@ Cas10ProxyHandlerTests.class, DefaultTicketGrantingTicketFactoryTests.class, DefaultEncodedTicketTests.class, + CasCoreTicketsMonitoringConfigurationTests.class, TransientSessionTicketExpirationPolicyBuilderTests.class, ProxyGrantingTicketExpirationPolicyBuilderTests.class, TicketValidationExceptionTests.class, diff --git a/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md b/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md index ff5d7d59a219..c396ff42f99f 100644 --- a/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md +++ b/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md @@ -101,7 +101,7 @@ The following SAML SP integrations, as samples, are provided by CAS: - + From 1216845b02ee83ab56d44c4b579c46350dbe5989 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 08:54:09 +0400 Subject: [PATCH 020/266] minor build fixes --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6e980467531f..71a2d9e9fa88 100644 --- a/gradle.properties +++ b/gradle.properties @@ -79,7 +79,7 @@ jakartaSoapApiVersion=3.0.0 jakartaAnnotationApiVersion=2.1.1 jaxbApiVersion=4.0.0 jaxbRuntimeVersion=4.0.1 -jaxbImplVersion=4.0.1 +jaxbImplVersion=4.0.2 ############################### # Swagger versions ############################### From 6214a4879398a1cf24892b5d17b04dee20433890 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 10:01:47 +0400 Subject: [PATCH 021/266] minor build fixes --- .../actuator-endpoint-reports/script.js | 14 ++++++++ .../actuator-endpoint-reports/script.json | 2 +- .../script.js | 4 ++- ...egisteredServiceUsernameProviderTests.java | 33 ++++++++++--------- ...CasCoreTicketsMonitoringConfiguration.java | 19 +++++------ 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.js b/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.js index 732fc83a86ac..c46efe1904fc 100644 --- a/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.js +++ b/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.js @@ -53,5 +53,19 @@ const cas = require('../../cas.js'); 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36' }, 200); } + + const ticketMetrics = [ + "addTicket", + "getTicket", + "getTickets" + ]; + for (let i = 0; i < ticketMetrics.length; i++) { + let url = `${baseUrl}metrics/org.apereo.cas.ticket.registry.TicketRegistry.${ticketMetrics[i]}`; + console.log(`Trying ${url}`); + await cas.doRequest(url, "GET", { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, 200); + } })(); diff --git a/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.json b/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.json index f0d6b98ebf96..19fd46f8ce62 100644 --- a/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.json +++ b/ci/tests/puppeteer/scenarios/actuator-endpoint-reports/script.json @@ -1,5 +1,5 @@ { - "dependencies": "reports,configuration-metadata-repository,events", + "dependencies": "reports,configuration-metadata-repository,events,monitor", "properties": [ "--cas.monitor.endpoints.endpoint.defaults.access=ANONYMOUS", diff --git a/ci/tests/puppeteer/scenarios/oidc-client-registration-protected/script.js b/ci/tests/puppeteer/scenarios/oidc-client-registration-protected/script.js index 3badf6c60b58..3316697e59c8 100644 --- a/ci/tests/puppeteer/scenarios/oidc-client-registration-protected/script.js +++ b/ci/tests/puppeteer/scenarios/oidc-client-registration-protected/script.js @@ -32,7 +32,9 @@ const assert = require('assert'); "id_token_encrypted_response_enc": "A128CBC-HS256", "userinfo_encrypted_response_alg": "RSA1_5", "userinfo_encrypted_response_enc": "A128CBC-HS256", - "contacts": ["sample@example.org", "user@example.org"] + "contacts": ["sample@example.org", "user@example.org"], + "grant_types": ["authorization_code"], + "response_types": ["code"], }; body = JSON.stringify(service, undefined, 2); diff --git a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java index e5875ac9b46c..9203017dac05 100644 --- a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java +++ b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/GroovyRegisteredServiceUsernameProviderTests.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -36,53 +37,53 @@ public class GroovyRegisteredServiceUsernameProviderTests { @Test public void verifyUsernameProvider() { - val p = new GroovyRegisteredServiceUsernameProvider(); - p.setGroovyScript("classpath:uid.groovy"); + val provider = new GroovyRegisteredServiceUsernameProvider(); + provider.setGroovyScript("classpath:uid.groovy"); val usernameContext = RegisteredServiceUsernameProviderContext.builder() .registeredService(RegisteredServiceTestUtils.getRegisteredService()) .service(RegisteredServiceTestUtils.getService()) .principal(RegisteredServiceTestUtils.getPrincipal()) .build(); - val id = p.resolveUsername(usernameContext); + val id = provider.resolveUsername(usernameContext); assertEquals("fromscript", id); } @Test public void verifyUsernameProviderInline() { - val p = new GroovyRegisteredServiceUsernameProvider(); - p.setGroovyScript("groovy { return attributes['uid'] + '123456789' }"); + val provider = new GroovyRegisteredServiceUsernameProvider(); + provider.setGroovyScript("groovy { return attributes['uid'] + '123456789' }"); val usernameContext = RegisteredServiceUsernameProviderContext.builder() .registeredService(RegisteredServiceTestUtils.getRegisteredService()) .service(RegisteredServiceTestUtils.getService()) .principal(RegisteredServiceTestUtils.getPrincipal("casuser", CollectionUtils.wrap("uid", "CAS-System"))) .build(); - val id = p.resolveUsername(usernameContext); + val id = provider.resolveUsername(usernameContext); assertEquals("CAS-System123456789", id); } @Test public void verifyUsernameProviderInlineAsList() { - val p = new GroovyRegisteredServiceUsernameProvider(); - p.setGroovyScript("groovy { return attributes['uid'][0] + '123456789' }"); + val provider = new GroovyRegisteredServiceUsernameProvider(); + provider.setGroovyScript("groovy { return attributes['uid'][0] + '123456789' }"); val usernameContext = RegisteredServiceUsernameProviderContext.builder() .registeredService(RegisteredServiceTestUtils.getRegisteredService()) .service(RegisteredServiceTestUtils.getService()) - .principal(RegisteredServiceTestUtils.getPrincipal("casuser", CollectionUtils.wrap("uid", "CAS-System"))) + .principal(RegisteredServiceTestUtils.getPrincipal("casuser", CollectionUtils.wrap("uid", List.of("CAS-System")))) .build(); - val id = p.resolveUsername(usernameContext); + val id = provider.resolveUsername(usernameContext); assertEquals("CAS-System123456789", id); } @Test public void verifySerializationToJson() throws IOException { - val p = new GroovyRegisteredServiceUsernameProvider(); - p.setGroovyScript("groovy { return 'something' }"); - p.setEncryptUsername(true); - p.setCanonicalizationMode("NONE"); - MAPPER.writeValue(JSON_FILE, p); + val provider = new GroovyRegisteredServiceUsernameProvider(); + provider.setGroovyScript("groovy { return 'something' }"); + provider.setEncryptUsername(true); + provider.setCanonicalizationMode("NONE"); + MAPPER.writeValue(JSON_FILE, provider); val repositoryRead = MAPPER.readValue(JSON_FILE, GroovyRegisteredServiceUsernameProvider.class); - assertEquals(p, repositoryRead); + assertEquals(provider, repositoryRead); } } diff --git a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java index 7f8ef129db5e..8bc00c68ba69 100644 --- a/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java +++ b/core/cas-server-core-tickets/src/main/java/org/apereo/cas/config/CasCoreTicketsMonitoringConfiguration.java @@ -13,13 +13,14 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; -import org.jooq.lambda.Unchecked; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.core.Ordered; /** * This is {@link CasCoreTicketsMonitoringConfiguration}. @@ -35,6 +36,7 @@ }) @ConditionalOnBean(name = ExecutableObserver.BEAN_NAME) @AutoConfiguration +@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE) public class CasCoreTicketsMonitoringConfiguration { @Bean @@ -48,16 +50,11 @@ public TicketRegistryMonitoringAspect ticketRegistryMonitoringAspect(final Objec @SuppressWarnings("UnusedMethod") record TicketRegistryMonitoringAspect(ObjectProvider observerProvider) { @Around("allComponentsInTicketRegistryNamespace()") - public Object aroundTicketRegistryOperations(final ProceedingJoinPoint joinPoint) { - return observerProvider - .stream() - .map(Unchecked.function(observer -> { - val taskName = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName(); - val task = new MonitorableTask(taskName); - return observer.supply(task, () -> executeJoinpoint(joinPoint)); - })) - .findFirst() - .orElseGet(() -> executeJoinpoint(joinPoint)); + public Object aroundTicketRegistryOperations(final ProceedingJoinPoint joinPoint) throws Throwable { + val observer = observerProvider.getObject(); + val taskName = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName(); + val task = new MonitorableTask(taskName); + return observer.supply(task, () -> executeJoinpoint(joinPoint)); } private static Object executeJoinpoint(final ProceedingJoinPoint joinPoint) { From 7d5ff13844a815bf9bae82cdccd731a1c28766d9 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 10:02:10 +0400 Subject: [PATCH 022/266] default supported response/grant types in oidc reg requests --- .../cas/oidc/OidcConfigurationContext.java | 3 + ...ClientConfigurationEndpointController.java | 2 +- ...dcClientRegistrationRequestTranslator.java | 230 +-------------- ...ltClientRegistrationRequestTranslator.java | 271 ++++++++++++++++++ ...cClientRegistrationEndpointController.java | 2 +- .../cas/oidc/config/OidcConfiguration.java | 15 + ...entRegistrationRequestTranslatorTests.java | 12 +- 7 files changed, 305 insertions(+), 230 deletions(-) create mode 100644 support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/OidcConfigurationContext.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/OidcConfigurationContext.java index 1192f50f48bd..5eda8c90e7da 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/OidcConfigurationContext.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/OidcConfigurationContext.java @@ -5,6 +5,7 @@ import org.apereo.cas.oidc.discovery.OidcServerDiscoverySettings; import org.apereo.cas.oidc.issuer.OidcIssuerService; import org.apereo.cas.oidc.util.OidcRequestSupport; +import org.apereo.cas.oidc.web.controllers.dynareg.OidcClientRegistrationRequestTranslator; import org.apereo.cas.support.oauth.web.endpoints.OAuth20ConfigurationContext; import org.apereo.cas.ticket.ExpirationPolicyBuilder; import org.apereo.cas.ticket.IdTokenGeneratorService; @@ -42,4 +43,6 @@ public class OidcConfigurationContext extends OAuth20ConfigurationContext { private final ExpirationPolicyBuilder idTokenExpirationPolicy; private final JwtBuilder responseModeJwtBuilder; + + private final OidcClientRegistrationRequestTranslator clientRegistrationRequestTranslator; } diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientConfigurationEndpointController.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientConfigurationEndpointController.java index 2b28289345a4..4576a5f7c975 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientConfigurationEndpointController.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientConfigurationEndpointController.java @@ -104,7 +104,7 @@ public ResponseEntity handleUpdates( val registrationRequest = (OidcClientRegistrationRequest) getConfigurationContext() .getClientRegistrationRequestSerializer().from(jsonInput); LOGGER.debug("Received client registration request [{}]", registrationRequest); - service = new OidcClientRegistrationRequestTranslator(getConfigurationContext()) + service = getConfigurationContext().getClientRegistrationRequestTranslator() .translate(registrationRequest, Optional.of(service)); } val clientSecretExp = Beans.newDuration(getConfigurationContext().getCasProperties() diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java index 96e7a2814d3e..8784120c9222 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslator.java @@ -1,58 +1,18 @@ package org.apereo.cas.oidc.web.controllers.dynareg; -import org.apereo.cas.configuration.support.Beans; -import org.apereo.cas.oidc.OidcConfigurationContext; import org.apereo.cas.oidc.dynareg.OidcClientRegistrationRequest; -import org.apereo.cas.oidc.profile.OidcUserProfileSigningAndEncryptionService; -import org.apereo.cas.services.DefaultRegisteredServiceContact; -import org.apereo.cas.services.DefaultRegisteredServiceMultifactorPolicy; import org.apereo.cas.services.OidcRegisteredService; -import org.apereo.cas.services.OidcSubjectTypes; -import org.apereo.cas.services.PairwiseOidcRegisteredServiceUsernameAttributeProvider; -import org.apereo.cas.support.oauth.util.OAuth20Utils; -import org.apereo.cas.util.HttpUtils; -import org.apereo.cas.util.RandomUtils; -import org.apereo.cas.util.function.FunctionUtils; -import org.apereo.cas.util.serialization.JacksonObjectMapperFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.hc.core5.http.HttpEntityContainer; -import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.HttpStatus; -import org.hjson.JsonValue; -import org.springframework.http.HttpMethod; - -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Objects; import java.util.Optional; /** * This is {@link OidcClientRegistrationRequestTranslator}. * * @author Misagh Moayyed - * @since 6.6.0 + * @since 7.0.0 */ -@RequiredArgsConstructor -@Slf4j -public class OidcClientRegistrationRequestTranslator { - private static final ObjectMapper MAPPER = JacksonObjectMapperFactory.builder() - .defaultTypingEnabled(false).build().toObjectMapper(); - - private static final int GENERATED_CLIENT_NAME_LENGTH = 8; - - private final OidcConfigurationContext context; - +@FunctionalInterface +public interface OidcClientRegistrationRequestTranslator { /** * Translate request into a response and store the service. * @@ -61,185 +21,7 @@ public class OidcClientRegistrationRequestTranslator { * @return the service * @throws Exception the exception */ - public OidcRegisteredService translate( - final OidcClientRegistrationRequest registrationRequest, - final Optional givenService) throws Exception { - - val containsFragment = registrationRequest.getRedirectUris() - .stream() - .anyMatch(uri -> uri.contains("#")); - if (containsFragment) { - throw new IllegalArgumentException("Redirect URI cannot contain a fragment"); - } - - val servicesManager = context.getServicesManager(); - val registeredService = givenService.orElseGet(() -> registrationRequest.getRedirectUris() - .stream() - .map(uri -> (OidcRegisteredService) OAuth20Utils.getRegisteredOAuthServiceByRedirectUri(servicesManager, uri)) - .filter(Objects::nonNull) - .findFirst() - .orElseGet(OidcRegisteredService::new)); - - if (StringUtils.isNotBlank(registrationRequest.getClientName())) { - registeredService.setName(registrationRequest.getClientName()); - } else if (StringUtils.isBlank(registeredService.getName())) { - registeredService.setName(RandomUtils.randomAlphabetic(GENERATED_CLIENT_NAME_LENGTH)); - } - - val serviceId = String.join("|", registrationRequest.getRedirectUris()); - registeredService.setServiceId(serviceId); - - registeredService.setSectorIdentifierUri(registrationRequest.getSectorIdentifierUri()); - registeredService.setSubjectType(registrationRequest.getSubjectType()); - if (StringUtils.equalsIgnoreCase(OidcSubjectTypes.PAIRWISE.getType(), registeredService.getSubjectType())) { - registeredService.setUsernameAttributeProvider(new PairwiseOidcRegisteredServiceUsernameAttributeProvider()); - } - - if (StringUtils.isNotBlank(registrationRequest.getJwksUri())) { - registeredService.setJwks(registrationRequest.getJwksUri()); - } else { - val jwks = registrationRequest.getJwks(); - if (jwks != null && !jwks.getJsonWebKeys().isEmpty()) { - jwks.getJsonWebKeys().stream() - .filter(key -> StringUtils.isBlank(key.getKeyId())) - .forEach(key -> key.setKeyId(RandomUtils.randomAlphabetic(6))); - registeredService.setJwks(jwks.toJson()); - } - } - - FunctionUtils.doIfNotBlank(registrationRequest.getTokenEndpointAuthMethod(), - __ -> registeredService.setTokenEndpointAuthenticationMethod(registrationRequest.getTokenEndpointAuthMethod())); - - if (StringUtils.isBlank(registeredService.getClientId())) { - registeredService.setClientId(context.getClientIdGenerator().getNewString()); - } - if (StringUtils.isBlank(registeredService.getClientSecret())) { - registeredService.setClientSecret(context.getClientSecretGenerator().getNewString()); - } - registeredService.setEvaluationOrder(0); - val urls = org.springframework.util.StringUtils.collectionToCommaDelimitedString( - registrationRequest.getPostLogoutRedirectUris()); - registeredService.setLogoutUrl(urls); - - - FunctionUtils.doIfNotBlank(registrationRequest.getLogo(), __ -> registeredService.setLogo(registrationRequest.getLogo())); - FunctionUtils.doIfNotBlank(registrationRequest.getPolicyUri(), __ -> registeredService.setInformationUrl(registrationRequest.getPolicyUri())); - FunctionUtils.doIfNotBlank(registrationRequest.getTermsOfUseUri(), __ -> registeredService.setPrivacyUrl(registrationRequest.getTermsOfUseUri())); - - FunctionUtils.doIfNotNull(registrationRequest.getGrantTypes(), - __ -> registeredService.setSupportedGrantTypes(new HashSet<>(registrationRequest.getGrantTypes()))); - FunctionUtils.doIfNotNull(registrationRequest.getResponseTypes(), - __ -> registeredService.setSupportedResponseTypes(new HashSet<>(registrationRequest.getResponseTypes()))); - - if (!StringUtils.equalsIgnoreCase("none", registrationRequest.getUserInfoSignedReponseAlg())) { - registeredService.setUserInfoSigningAlg(registrationRequest.getUserInfoSignedReponseAlg()); - } - registeredService.setUserInfoEncryptedResponseAlg(registrationRequest.getUserInfoEncryptedResponseAlg()); - - if (StringUtils.isNotBlank(registeredService.getUserInfoEncryptedResponseAlg())) { - if (StringUtils.isBlank(registrationRequest.getUserInfoEncryptedResponseEncoding())) { - registeredService.setUserInfoEncryptedResponseEncoding( - OidcUserProfileSigningAndEncryptionService.USER_INFO_RESPONSE_ENCRYPTION_ENCODING_DEFAULT); - } else { - registeredService.setUserInfoEncryptedResponseEncoding(registrationRequest.getUserInfoEncryptedResponseEncoding()); - } - } - - val properties = context.getCasProperties(); - val supportedScopes = new HashSet<>(properties.getAuthn().getOidc().getDiscovery().getScopes()); - registeredService.setScopes(supportedScopes); - val processedScopes = new LinkedHashSet<>(supportedScopes); - registeredService.setScopes(processedScopes); - - if (!registrationRequest.getDefaultAcrValues().isEmpty()) { - val multifactorPolicy = new DefaultRegisteredServiceMultifactorPolicy(); - multifactorPolicy.setMultifactorAuthenticationProviders(new HashSet<>(registrationRequest.getDefaultAcrValues())); - registeredService.setMultifactorAuthenticationPolicy(multifactorPolicy); - } - - if (StringUtils.isNotBlank(registrationRequest.getIdTokenSignedResponseAlg())) { - registeredService.setIdTokenSigningAlg(registrationRequest.getIdTokenSignedResponseAlg()); - registeredService.setSignIdToken(true); - } - - if (StringUtils.isNotBlank(registrationRequest.getIdTokenEncryptedResponseAlg())) { - registeredService.setIdTokenEncryptionAlg(registrationRequest.getIdTokenEncryptedResponseAlg()); - registeredService.setEncryptIdToken(true); - } - - if (StringUtils.isNotBlank(registrationRequest.getIdTokenEncryptedResponseEncoding())) { - registeredService.setIdTokenEncryptionEncoding(registrationRequest.getIdTokenEncryptedResponseEncoding()); - registeredService.setEncryptIdToken(true); - } - - registeredService.getContacts().clear(); - registrationRequest.getContacts().forEach(c -> { - val contact = new DefaultRegisteredServiceContact(); - if (c.contains("@")) { - contact.setEmail(c); - contact.setName(c.substring(0, c.indexOf('@'))); - } else { - contact.setName(c); - } - registeredService.getContacts().add(contact); - }); - val clientSecretExp = Beans.newDuration(context.getCasProperties() - .getAuthn().getOidc().getRegistration().getClientSecretExpiration()).toSeconds(); - if (clientSecretExp > 0 && registeredService.getClientSecretExpiration() <= 0) { - val currentTime = ZonedDateTime.now(ZoneOffset.UTC); - val expirationDate = currentTime.plusSeconds(clientSecretExp); - LOGGER.debug("Client secret shall expire at [{}] while now is [{}]", expirationDate, currentTime); - registeredService.setClientSecretExpiration(expirationDate.toEpochSecond()); - } - - registeredService.setDescription("Registered service ".concat(registeredService.getName())); - validate(registrationRequest, registeredService); - return registeredService; - } - - private void validate(final OidcClientRegistrationRequest registrationRequest, - final OidcRegisteredService registeredService) throws Exception { - if (StringUtils.isNotBlank(registeredService.getSectorIdentifierUri())) { - HttpResponse sectorResponse = null; - try { - val exec = HttpUtils.HttpExecutionRequest.builder() - .method(HttpMethod.GET) - .url(registeredService.getSectorIdentifierUri()) - .build(); - sectorResponse = HttpUtils.execute(exec); - if (sectorResponse != null && sectorResponse.getCode() == HttpStatus.SC_OK) { - val result = IOUtils.toString(((HttpEntityContainer) sectorResponse).getEntity().getContent(), StandardCharsets.UTF_8); - val expectedType = MAPPER.getTypeFactory().constructParametricType(List.class, String.class); - val urls = MAPPER.readValue(JsonValue.readHjson(result).toString(), expectedType); - if (!urls.equals(registrationRequest.getRedirectUris())) { - throw new IllegalArgumentException("Invalid sector identifier uri"); - } - } - } finally { - HttpUtils.close(sectorResponse); - } - } - - val oidc = context.getCasProperties().getAuthn().getOidc(); - if (!oidc.getRegistration().getDynamicClientRegistrationMode().isProtected() - && (StringUtils.isNotBlank(registrationRequest.getPolicyUri()) || StringUtils.isNotBlank(registrationRequest.getLogo()))) { - val hosts = registrationRequest.getRedirectUris() - .stream() - .map(uri -> FunctionUtils.doUnchecked(() -> new URI(uri).getHost())).toList(); - if (StringUtils.isNotBlank(registrationRequest.getLogo())) { - val logo = new URI(registrationRequest.getLogo()).getHost(); - if (!hosts.contains(logo)) { - throw new IllegalArgumentException("Invalid logo uri from an unknown host"); - } - } - - if (StringUtils.isNotBlank(registrationRequest.getPolicyUri())) { - val policy = new URI(registrationRequest.getPolicyUri()).getHost(); - if (!hosts.contains(policy)) { - throw new IllegalArgumentException("Invalid policy uri from an unknown host"); - } - } - } - } - + OidcRegisteredService translate( + OidcClientRegistrationRequest registrationRequest, + Optional givenService) throws Exception; } diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java new file mode 100644 index 000000000000..1ca16c62be7e --- /dev/null +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java @@ -0,0 +1,271 @@ +package org.apereo.cas.oidc.web.controllers.dynareg; + +import org.apereo.cas.configuration.support.Beans; +import org.apereo.cas.oidc.OidcConfigurationContext; +import org.apereo.cas.oidc.dynareg.OidcClientRegistrationRequest; +import org.apereo.cas.oidc.profile.OidcUserProfileSigningAndEncryptionService; +import org.apereo.cas.services.DefaultRegisteredServiceContact; +import org.apereo.cas.services.DefaultRegisteredServiceMultifactorPolicy; +import org.apereo.cas.services.OidcRegisteredService; +import org.apereo.cas.services.OidcSubjectTypes; +import org.apereo.cas.services.PairwiseOidcRegisteredServiceUsernameAttributeProvider; +import org.apereo.cas.support.oauth.OAuth20GrantTypes; +import org.apereo.cas.support.oauth.OAuth20ResponseTypes; +import org.apereo.cas.support.oauth.util.OAuth20Utils; +import org.apereo.cas.util.CollectionUtils; +import org.apereo.cas.util.HttpUtils; +import org.apereo.cas.util.RandomUtils; +import org.apereo.cas.util.function.FunctionUtils; +import org.apereo.cas.util.serialization.JacksonObjectMapperFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.hc.core5.http.HttpEntityContainer; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.hjson.JsonValue; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.http.HttpMethod; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * This is {@link OidcDefaultClientRegistrationRequestTranslator}. + * + * @author Misagh Moayyed + * @since 6.6.0 + */ +@RequiredArgsConstructor +@Slf4j +public class OidcDefaultClientRegistrationRequestTranslator implements OidcClientRegistrationRequestTranslator { + private static final ObjectMapper MAPPER = JacksonObjectMapperFactory.builder() + .defaultTypingEnabled(false).build().toObjectMapper(); + + private static final int GENERATED_CLIENT_NAME_LENGTH = 8; + + private final ObjectProvider configurationContext; + + @Override + public OidcRegisteredService translate( + final OidcClientRegistrationRequest registrationRequest, + final Optional givenService) throws Exception { + + val context = configurationContext.getObject(); + + val containsFragment = registrationRequest.getRedirectUris() + .stream() + .anyMatch(uri -> uri.contains("#")); + if (containsFragment) { + throw new IllegalArgumentException("Redirect URI cannot contain a fragment"); + } + + val servicesManager = context.getServicesManager(); + val registeredService = givenService.orElseGet(() -> registrationRequest.getRedirectUris() + .stream() + .map(uri -> (OidcRegisteredService) OAuth20Utils.getRegisteredOAuthServiceByRedirectUri(servicesManager, uri)) + .filter(Objects::nonNull) + .findFirst() + .orElseGet(OidcRegisteredService::new)); + + if (StringUtils.isNotBlank(registrationRequest.getClientName())) { + registeredService.setName(registrationRequest.getClientName()); + } else if (StringUtils.isBlank(registeredService.getName())) { + registeredService.setName(RandomUtils.randomAlphabetic(GENERATED_CLIENT_NAME_LENGTH)); + } + + val serviceId = String.join("|", registrationRequest.getRedirectUris()); + registeredService.setServiceId(serviceId); + + registeredService.setSectorIdentifierUri(registrationRequest.getSectorIdentifierUri()); + registeredService.setSubjectType(registrationRequest.getSubjectType()); + if (StringUtils.equalsIgnoreCase(OidcSubjectTypes.PAIRWISE.getType(), registeredService.getSubjectType())) { + registeredService.setUsernameAttributeProvider(new PairwiseOidcRegisteredServiceUsernameAttributeProvider()); + } + + if (StringUtils.isNotBlank(registrationRequest.getJwksUri())) { + registeredService.setJwks(registrationRequest.getJwksUri()); + } else { + val jwks = registrationRequest.getJwks(); + if (jwks != null && !jwks.getJsonWebKeys().isEmpty()) { + jwks.getJsonWebKeys().stream() + .filter(key -> StringUtils.isBlank(key.getKeyId())) + .forEach(key -> key.setKeyId(RandomUtils.randomAlphabetic(6))); + registeredService.setJwks(jwks.toJson()); + } + } + + FunctionUtils.doIfNotBlank(registrationRequest.getTokenEndpointAuthMethod(), + __ -> registeredService.setTokenEndpointAuthenticationMethod(registrationRequest.getTokenEndpointAuthMethod())); + + if (StringUtils.isBlank(registeredService.getClientId())) { + registeredService.setClientId(context.getClientIdGenerator().getNewString()); + } + if (StringUtils.isBlank(registeredService.getClientSecret())) { + registeredService.setClientSecret(context.getClientSecretGenerator().getNewString()); + } + registeredService.setEvaluationOrder(0); + val urls = org.springframework.util.StringUtils.collectionToCommaDelimitedString( + registrationRequest.getPostLogoutRedirectUris()); + registeredService.setLogoutUrl(urls); + + FunctionUtils.doIfNotBlank(registrationRequest.getLogo(), __ -> registeredService.setLogo(registrationRequest.getLogo())); + FunctionUtils.doIfNotBlank(registrationRequest.getPolicyUri(), __ -> registeredService.setInformationUrl(registrationRequest.getPolicyUri())); + FunctionUtils.doIfNotBlank(registrationRequest.getTermsOfUseUri(), __ -> registeredService.setPrivacyUrl(registrationRequest.getTermsOfUseUri())); + + processUserInfoSigningAndEncryption(registrationRequest, registeredService); + processScopesAndResponsesAndGrants(registrationRequest, registeredService); + + if (!registrationRequest.getDefaultAcrValues().isEmpty()) { + val multifactorPolicy = new DefaultRegisteredServiceMultifactorPolicy(); + multifactorPolicy.setMultifactorAuthenticationProviders(new HashSet<>(registrationRequest.getDefaultAcrValues())); + registeredService.setMultifactorAuthenticationPolicy(multifactorPolicy); + } + + processIdTokenSigningAndEncryption(registrationRequest, registeredService); + processContacts(registrationRequest, registeredService); + processClientSecretExpiration(context, registeredService); + + registeredService.setDescription("Registered service ".concat(registeredService.getName())); + validate(registrationRequest, registeredService); + return registeredService; + } + + private void processScopesAndResponsesAndGrants(final OidcClientRegistrationRequest registrationRequest, + final OidcRegisteredService registeredService) { + val context = configurationContext.getObject(); + FunctionUtils.doIfNotNull(registrationRequest.getGrantTypes(), + __ -> registeredService.setSupportedGrantTypes(new HashSet<>(registrationRequest.getGrantTypes()))); + FunctionUtils.doIfNotNull(registrationRequest.getResponseTypes(), + __ -> registeredService.setSupportedResponseTypes(new HashSet<>(registrationRequest.getResponseTypes()))); + + val properties = context.getCasProperties(); + val supportedScopes = new HashSet<>(properties.getAuthn().getOidc().getDiscovery().getScopes()); + registeredService.setScopes(supportedScopes); + if (registeredService.getSupportedGrantTypes().isEmpty()) { + registeredService.setSupportedGrantTypes(CollectionUtils.wrapHashSet(OAuth20GrantTypes.AUTHORIZATION_CODE.getType())); + } + if (registeredService.getSupportedResponseTypes().isEmpty()) { + registeredService.setSupportedResponseTypes(CollectionUtils.wrapHashSet(OAuth20ResponseTypes.CODE.getType())); + } + } + + private static void processUserInfoSigningAndEncryption(final OidcClientRegistrationRequest registrationRequest, + final OidcRegisteredService registeredService) { + if (!StringUtils.equalsIgnoreCase("none", registrationRequest.getUserInfoSignedReponseAlg())) { + registeredService.setUserInfoSigningAlg(registrationRequest.getUserInfoSignedReponseAlg()); + } + registeredService.setUserInfoEncryptedResponseAlg(registrationRequest.getUserInfoEncryptedResponseAlg()); + if (StringUtils.isNotBlank(registeredService.getUserInfoEncryptedResponseAlg())) { + if (StringUtils.isBlank(registrationRequest.getUserInfoEncryptedResponseEncoding())) { + registeredService.setUserInfoEncryptedResponseEncoding( + OidcUserProfileSigningAndEncryptionService.USER_INFO_RESPONSE_ENCRYPTION_ENCODING_DEFAULT); + } else { + registeredService.setUserInfoEncryptedResponseEncoding(registrationRequest.getUserInfoEncryptedResponseEncoding()); + } + } + } + + private static void processIdTokenSigningAndEncryption(final OidcClientRegistrationRequest registrationRequest, + final OidcRegisteredService registeredService) { + if (StringUtils.isNotBlank(registrationRequest.getIdTokenSignedResponseAlg())) { + registeredService.setIdTokenSigningAlg(registrationRequest.getIdTokenSignedResponseAlg()); + registeredService.setSignIdToken(true); + } + + if (StringUtils.isNotBlank(registrationRequest.getIdTokenEncryptedResponseAlg())) { + registeredService.setIdTokenEncryptionAlg(registrationRequest.getIdTokenEncryptedResponseAlg()); + registeredService.setEncryptIdToken(true); + } + + if (StringUtils.isNotBlank(registrationRequest.getIdTokenEncryptedResponseEncoding())) { + registeredService.setIdTokenEncryptionEncoding(registrationRequest.getIdTokenEncryptedResponseEncoding()); + registeredService.setEncryptIdToken(true); + } + } + + private static void processClientSecretExpiration(final OidcConfigurationContext context, + final OidcRegisteredService registeredService) { + val clientSecretExp = Beans.newDuration(context.getCasProperties() + .getAuthn().getOidc().getRegistration().getClientSecretExpiration()).toSeconds(); + if (clientSecretExp > 0 && registeredService.getClientSecretExpiration() <= 0) { + val currentTime = ZonedDateTime.now(ZoneOffset.UTC); + val expirationDate = currentTime.plusSeconds(clientSecretExp); + LOGGER.debug("Client secret shall expire at [{}] while now is [{}]", expirationDate, currentTime); + registeredService.setClientSecretExpiration(expirationDate.toEpochSecond()); + } + } + + private static void processContacts(final OidcClientRegistrationRequest registrationRequest, + final OidcRegisteredService registeredService) { + registeredService.getContacts().clear(); + registrationRequest.getContacts().forEach(givenContact -> { + val contact = new DefaultRegisteredServiceContact(); + if (givenContact.contains("@")) { + contact.setEmail(givenContact); + contact.setName(givenContact.substring(0, givenContact.indexOf('@'))); + } else { + contact.setName(givenContact); + } + registeredService.getContacts().add(contact); + }); + } + + private void validate(final OidcClientRegistrationRequest registrationRequest, + final OidcRegisteredService registeredService) throws Exception { + val context = configurationContext.getObject(); + if (StringUtils.isNotBlank(registeredService.getSectorIdentifierUri())) { + HttpResponse sectorResponse = null; + try { + val exec = HttpUtils.HttpExecutionRequest.builder() + .method(HttpMethod.GET) + .url(registeredService.getSectorIdentifierUri()) + .build(); + sectorResponse = HttpUtils.execute(exec); + if (sectorResponse != null && sectorResponse.getCode() == HttpStatus.SC_OK) { + val result = IOUtils.toString(((HttpEntityContainer) sectorResponse).getEntity().getContent(), StandardCharsets.UTF_8); + val expectedType = MAPPER.getTypeFactory().constructParametricType(List.class, String.class); + val urls = MAPPER.readValue(JsonValue.readHjson(result).toString(), expectedType); + if (!urls.equals(registrationRequest.getRedirectUris())) { + throw new IllegalArgumentException("Invalid sector identifier uri"); + } + } + } finally { + HttpUtils.close(sectorResponse); + } + } + + val oidc = context.getCasProperties().getAuthn().getOidc(); + if (!oidc.getRegistration().getDynamicClientRegistrationMode().isProtected() + && (StringUtils.isNotBlank(registrationRequest.getPolicyUri()) || StringUtils.isNotBlank(registrationRequest.getLogo()))) { + val hosts = registrationRequest.getRedirectUris() + .stream() + .map(uri -> FunctionUtils.doUnchecked(() -> new URI(uri).getHost())).toList(); + if (StringUtils.isNotBlank(registrationRequest.getLogo())) { + val logo = new URI(registrationRequest.getLogo()).getHost(); + if (!hosts.contains(logo)) { + throw new IllegalArgumentException("Invalid logo uri from an unknown host"); + } + } + + if (StringUtils.isNotBlank(registrationRequest.getPolicyUri())) { + val policy = new URI(registrationRequest.getPolicyUri()).getHost(); + if (!hosts.contains(policy)) { + throw new IllegalArgumentException("Invalid policy uri from an unknown host"); + } + } + } + } + +} diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDynamicClientRegistrationEndpointController.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDynamicClientRegistrationEndpointController.java index 6726ba7d74c3..8624623de0d1 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDynamicClientRegistrationEndpointController.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDynamicClientRegistrationEndpointController.java @@ -72,7 +72,7 @@ public ResponseEntity handleRequestInternal( val registrationRequest = (OidcClientRegistrationRequest) getConfigurationContext() .getClientRegistrationRequestSerializer().from(jsonInput); LOGGER.debug("Received client registration request [{}]", registrationRequest); - val registeredService = new OidcClientRegistrationRequestTranslator(getConfigurationContext()) + val registeredService = getConfigurationContext().getClientRegistrationRequestTranslator() .translate(registrationRequest, Optional.empty()); registeredService.markAsDynamicallyRegistered(); diff --git a/support/cas-server-support-oidc/src/main/java/org/apereo/cas/oidc/config/OidcConfiguration.java b/support/cas-server-support-oidc/src/main/java/org/apereo/cas/oidc/config/OidcConfiguration.java index 910f29541da4..67bc61684935 100644 --- a/support/cas-server-support-oidc/src/main/java/org/apereo/cas/oidc/config/OidcConfiguration.java +++ b/support/cas-server-support-oidc/src/main/java/org/apereo/cas/oidc/config/OidcConfiguration.java @@ -57,6 +57,8 @@ import org.apereo.cas.oidc.web.OidcCasClientRedirectActionBuilder; import org.apereo.cas.oidc.web.OidcClientSecretValidator; import org.apereo.cas.oidc.web.OidcConsentApprovalViewResolver; +import org.apereo.cas.oidc.web.controllers.dynareg.OidcClientRegistrationRequestTranslator; +import org.apereo.cas.oidc.web.controllers.dynareg.OidcDefaultClientRegistrationRequestTranslator; import org.apereo.cas.oidc.web.response.OidcJwtResponseModeCipherExecutor; import org.apereo.cas.oidc.web.response.OidcRegisteredServiceJwtResponseModeCipherExecutor; import org.apereo.cas.oidc.web.response.OidcResponseModeFormPostJwtBuilder; @@ -644,6 +646,8 @@ public static class OidcContextConfiguration { @ConditionalOnMissingBean(name = OidcConfigurationContext.BEAN_NAME) @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public OidcConfigurationContext oidcConfigurationContext( + @Qualifier("oidcClientRegistrationRequestTranslator") + final OidcClientRegistrationRequestTranslator oidcClientRegistrationRequestTranslator, @Qualifier("oidcResponseModeJwtBuilder") final JwtBuilder oidcResponseModeJwtBuilder, @Qualifier(OAuth20ClientSecretValidator.BEAN_NAME) @@ -732,6 +736,7 @@ public OidcConfigurationContext oidcConfigurationContext( .discoverySettings(oidcServerDiscoverySettings) .requestParameterResolver(oauthRequestParameterResolver) .issuerService(oidcIssuerService) + .clientRegistrationRequestTranslator(oidcClientRegistrationRequestTranslator) .ticketFactory(ticketFactory) .idTokenClaimCollector(oidcIdTokenClaimCollector) .idTokenGeneratorService(oidcIdTokenGenerator) @@ -842,6 +847,15 @@ public StringSerializer clientRegistrationRequest return new OidcClientRegistrationRequestSerializer(); } + @Bean + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @ConditionalOnMissingBean(name = "oidcClientRegistrationRequestTranslator") + public OidcClientRegistrationRequestTranslator oidcClientRegistrationRequestTranslator( + @Qualifier(OidcConfigurationContext.BEAN_NAME) + final ObjectProvider oidcConfigurationContext) { + return new OidcDefaultClientRegistrationRequestTranslator(oidcConfigurationContext); + } + @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) public OAuth20AuthorizationModelAndViewBuilder oauthAuthorizationModelAndViewBuilder( @@ -934,6 +948,7 @@ public OAuth20ResponseModeBuilder oauthFormPostJwtResponseModeBuilder( final ObjectProvider oidcConfigurationContext) { return new OidcResponseModeFormPostJwtBuilder(oidcConfigurationContext); } + @Bean @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) @ConditionalOnMissingBean(name = "oidcResponseModeJwtCipherExecutor") diff --git a/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslatorTests.java b/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslatorTests.java index a53302aea191..1e0eeb87ba16 100644 --- a/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslatorTests.java +++ b/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcClientRegistrationRequestTranslatorTests.java @@ -7,6 +7,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.TestPropertySource; import java.util.List; @@ -28,24 +30,26 @@ public class OidcClientRegistrationRequestTranslatorTests { @TestPropertySource(properties = "cas.authn.oidc.registration.dynamic-client-registration-mode=OPEN") public class OpenRegistrationMode extends AbstractOidcTests { + @Autowired + @Qualifier("oidcClientRegistrationRequestTranslator") + private OidcClientRegistrationRequestTranslator oidcClientRegistrationRequestTranslator; + @Test public void verifyBadLogo() throws Exception { - val translator = new OidcClientRegistrationRequestTranslator(oidcConfigurationContext); val registrationRequest = new OidcClientRegistrationRequest(); registrationRequest.setRedirectUris(List.of("https://apereo.github.io")); registrationRequest.setLogo("https://github.com/apereo.can"); assertThrows(IllegalArgumentException.class, - () -> translator.translate(registrationRequest, Optional.empty())); + () -> oidcClientRegistrationRequestTranslator.translate(registrationRequest, Optional.empty())); } @Test public void verifyBadPolicy() throws Exception { - val translator = new OidcClientRegistrationRequestTranslator(oidcConfigurationContext); val registrationRequest = new OidcClientRegistrationRequest(); registrationRequest.setRedirectUris(List.of("https://apereo.github.io")); registrationRequest.setPolicyUri("https://github.com/apereo.can"); assertThrows(IllegalArgumentException.class, - () -> translator.translate(registrationRequest, Optional.empty())); + () -> oidcClientRegistrationRequestTranslator.translate(registrationRequest, Optional.empty())); } } } From d6339bab0ce05be303e09cf54a5df82e32831944 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 10:08:35 +0400 Subject: [PATCH 023/266] process principal uid during attribute release only when attribute is missing --- .../AbstractRegisteredServiceAttributeReleasePolicy.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java b/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java index 47dad8b295d2..ab13c173ff3a 100644 --- a/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java +++ b/core/cas-server-core-authentication-attributes/src/main/java/org/apereo/cas/services/AbstractRegisteredServiceAttributeReleasePolicy.java @@ -236,7 +236,7 @@ protected Map> resolveAttributesFromPrincipalAttributeRepos protected void insertPrincipalIdAsAttributeIfNeeded(final RegisteredServiceAttributeReleasePolicyContext context, final Map> attributesToRelease) { - if (StringUtils.isNotBlank(getPrincipalIdAttribute())) { + if (StringUtils.isNotBlank(getPrincipalIdAttribute()) && !attributesToRelease.containsKey(getPrincipalIdAttribute())) { LOGGER.debug("Attempting to resolve the principal id for service [{}]", context.getRegisteredService().getServiceId()); val usernameProvider = context.getRegisteredService().getUsernameAttributeProvider(); if (usernameProvider != null) { @@ -247,10 +247,9 @@ protected void insertPrincipalIdAsAttributeIfNeeded(final RegisteredServiceAttri .registeredService(context.getRegisteredService()) .releasingAttributes(attributesToRelease) .build(); - val id = usernameProvider.resolveUsername(usernameContext); LOGGER.debug("Releasing resolved principal id [{}] as attribute [{}]", id, getPrincipalIdAttribute()); - attributesToRelease.put(getPrincipalIdAttribute(), CollectionUtils.wrapList(context.getPrincipal().getId())); + attributesToRelease.put(getPrincipalIdAttribute(), CollectionUtils.wrapList(id)); } } } From 463cbc61d6070448e5028ece5dd4ac67476e5063 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 10:14:48 +0400 Subject: [PATCH 024/266] fix typos in documentation --- .../authentication/Configuring-SSO-Cookie.md | 2 +- .../Surrogate-Authentication-AccountSelection.md | 2 +- .../configuration/Configuration-Server-Management.md | 6 +++--- .../developer/Contributor-Guidelines.md | 2 +- .../integration/Delegate-Authentication-PostProcessing.md | 2 +- .../mfa/DuoSecurity-Authentication.md | 2 +- docs/cas-server-documentation/release_notes/RC3.md | 2 +- docs/cas-server-documentation/release_notes/RC6.md | 6 +++++- .../services/Configuring-Service-Proxy-Policy.md | 2 +- .../services/Configuring-Service-SSO-Policy.md | 2 +- 10 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/cas-server-documentation/authentication/Configuring-SSO-Cookie.md b/docs/cas-server-documentation/authentication/Configuring-SSO-Cookie.md index 88666b7b179a..3c7caddb8d00 100644 --- a/docs/cas-server-documentation/authentication/Configuring-SSO-Cookie.md +++ b/docs/cas-server-documentation/authentication/Configuring-SSO-Cookie.md @@ -91,7 +91,7 @@ The parameters that may be passed are as follows: {% tab samesitecookie Java %} -The cookie setting in CAS configuration may point to a Java class usonig its FQDN +The cookie setting in CAS configuration may point to a Java class using its FQDN that is tasked to generate the `SameAttribute` cookie attribute. ```java diff --git a/docs/cas-server-documentation/authentication/Surrogate-Authentication-AccountSelection.md b/docs/cas-server-documentation/authentication/Surrogate-Authentication-AccountSelection.md index b1a49ac0c69c..197971643ad5 100644 --- a/docs/cas-server-documentation/authentication/Surrogate-Authentication-AccountSelection.md +++ b/docs/cas-server-documentation/authentication/Surrogate-Authentication-AccountSelection.md @@ -54,7 +54,7 @@ any other username without any restrictions or additional checks.

To designate an account as a wildcard, the account store must be able to return and provide a list of diff --git a/docs/cas-server-documentation/configuration/Configuration-Server-Management.md b/docs/cas-server-documentation/configuration/Configuration-Server-Management.md index 222ba29ef011..f30a74a1b9cf 100644 --- a/docs/cas-server-documentation/configuration/Configuration-Server-Management.md +++ b/docs/cas-server-documentation/configuration/Configuration-Server-Management.md @@ -19,9 +19,9 @@ though at the cost of losing features and capabilities relevant for a cloud depl The CAS server web application responds to the following strategies that dictate how settings should be consumed. -| Strategy | Description | -|--------------------------------------------|------------------------------------------------------------------------------| -| [Standalone](Configuration-Server-Management-Standalone.html) | Default strategy. | +| Strategy | Description | +|------------------------------------------------------------------|----------------------------------------------------------------| +| [Standalone](Configuration-Server-Management-Standalone.html) | Default strategy. | | [Spring Cloud](Configuration-Server-Management-SpringCloud.html) | Externalized strategy using Spring Cloud configuration server. | ## Configuration Security diff --git a/docs/cas-server-documentation/developer/Contributor-Guidelines.md b/docs/cas-server-documentation/developer/Contributor-Guidelines.md index 2d322f02fe69..58fc614ab710 100644 --- a/docs/cas-server-documentation/developer/Contributor-Guidelines.md +++ b/docs/cas-server-documentation/developer/Contributor-Guidelines.md @@ -27,7 +27,7 @@ In the context of the Apereo CAS project, a *contribution* generally means the g of bug fixes, modest feature enhancements, documentation improvements, test cases, etc back to the project typically in the form of a pull request or patch. All such items and donations play a significant part in improving the state of the project and the software for all involved. Such contributions are concrete, actionable and measurable and signal back to the larger community that you, the contributor, are actively involved, engaged and concerned -with the overal health status and future direction of the project. Of course, for non-technical folks, contributions do not always equal writing some +with the overall health status and future direction of the project. Of course, for non-technical folks, contributions do not always equal writing some kind of code. That is only one of many possible options. We hope that you consider that as a good starting place and when all else fails, consider [supporting the project](https://apereo.github.io/cas/Support.html). diff --git a/docs/cas-server-documentation/integration/Delegate-Authentication-PostProcessing.md b/docs/cas-server-documentation/integration/Delegate-Authentication-PostProcessing.md index 86fb1127804b..8d1eab4c11c9 100644 --- a/docs/cas-server-documentation/integration/Delegate-Authentication-PostProcessing.md +++ b/docs/cas-server-documentation/integration/Delegate-Authentication-PostProcessing.md @@ -46,7 +46,7 @@ The parameters passed are as follows: | `logger` | The object responsible for issuing log messages such as `logger.info(...)`. | -## Preprocesing Authentication +## Preprocessing Authentication You may also opt into preprocessing the delegated authentication event prior to the final step in the process and before an SSO session is created. Preprocessing the authentication here allows one to manipulate and update the final authenticated principal before it's fully baked into the SSO session. diff --git a/docs/cas-server-documentation/mfa/DuoSecurity-Authentication.md b/docs/cas-server-documentation/mfa/DuoSecurity-Authentication.md index 2fca489f5bca..d1d82991c673 100644 --- a/docs/cas-server-documentation/mfa/DuoSecurity-Authentication.md +++ b/docs/cas-server-documentation/mfa/DuoSecurity-Authentication.md @@ -83,7 +83,7 @@ requests and of course, the user in question must not have been onboard, enrolle in Duo Security. The redirect URL to your enrollment application may include a special `principal` parameter that contains -the user's identity as JWT. Cipher operations and settings must be abled in CAS settings for Duo Security's +the user's identity as JWT. Cipher operations and settings must be enabled in CAS settings for Duo Security's registration before this parameter can be built and added to the final URL. {% include_cached casproperties.html properties="cas.authn.mfa.duo[].registration" %} diff --git a/docs/cas-server-documentation/release_notes/RC3.md b/docs/cas-server-documentation/release_notes/RC3.md index 714226c59c37..006f98404402 100644 --- a/docs/cas-server-documentation/release_notes/RC3.md +++ b/docs/cas-server-documentation/release_notes/RC3.md @@ -56,7 +56,7 @@ servlet container may need to downgrade the version of the Servlet specification be sorted out prior to the final GA release by the time Jetty `12` is released. - A handful of dependencies and libraries (i.e. OpenSAML, Pac4j, Spring Retry,) have yet to provide a final release version compatible with Spring Boot `3` and/or Jakarta APIs. These should hopefully finalize and publish a GA release in the next few release candidates. -- Apache BVal has been replaced with Hibernate Validator as the primary libary for bean validation. The former provides no support for Jakarta APIs, yet. +- Apache BVal has been replaced with Hibernate Validator as the primary library for bean validation. The former provides no support for Jakarta APIs, yet. - Support for Spring Cloud Sleuth has been removed, and will later on be replaced with Micrometer Tracing. - The [SCIM 2](https://github.com/pingidentity/scim2) library is replaced with an alternative that supports Jakarta APIs. diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index 046be9372584..f1150927fe4e 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -44,10 +44,14 @@ The following items are new improvements and enhancements presented in this rele ### Google Cloud Pub/Sub Ticket Registry A new ticket registry implementation backed by [Google Cloud's PubSub](../ticketing/GCP-PubSub-Ticket-Registry.html) is now available. + +### OpenID Connect Dynamic Registration + +Supported grant types and response types are recognized during [OpenID Connect Dynamic Registration](../authentication/OIDC-Authentication-Dynamic-Registration.html). +Furthermore, sensible defaults would be used if grant types or response types are not explicitly requested. ## Other Stuff -- Supported grant types and response types are recognized during [OpenID Connect Dynamic Registration](../authentication/OIDC-Authentication-Dynamic-Registration.html). - Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io/docs/observation) and then reported as metrics. - JSON and YAML service registries are able to auto-organize and store service definition files in dedicated directories identified by the service type. diff --git a/docs/cas-server-documentation/services/Configuring-Service-Proxy-Policy.md b/docs/cas-server-documentation/services/Configuring-Service-Proxy-Policy.md index c507b3599d96..fecf619e7aae 100644 --- a/docs/cas-server-documentation/services/Configuring-Service-Proxy-Policy.md +++ b/docs/cas-server-documentation/services/Configuring-Service-Proxy-Policy.md @@ -90,7 +90,7 @@ A proxy policy that reaches out to an external REST endpoint to determine proxy ``` Endpoints must be designed to accept/process `application/json`, where the request body will contain -the contents of the registered service definition, and the requesing PGT url is passed as `pgtUrl` request parameter. +the contents of the registered service definition, and the requesting PGT url is passed as `pgtUrl` request parameter. A successful `200` status code will allow proxy authentication to proceed. {% endtab %} diff --git a/docs/cas-server-documentation/services/Configuring-Service-SSO-Policy.md b/docs/cas-server-documentation/services/Configuring-Service-SSO-Policy.md index ae562e04cd36..c8b6f7c56baa 100644 --- a/docs/cas-server-documentation/services/Configuring-Service-SSO-Policy.md +++ b/docs/cas-server-documentation/services/Configuring-Service-SSO-Policy.md @@ -13,7 +13,7 @@ to participation in single sign-on sessions, creating SSO cookies, etc. ## Disable Service SSO Access -Participation in existing single signon sessions can be disabled on a per-application basis. For example, +Participation in existing single sign-on sessions can be disabled on a per-application basis. For example, the following service will be challenged to present credentials every time, thereby not using SSO: ```json From b944f470e954357f10574d826fa4a37969b64270 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 10:58:02 +0400 Subject: [PATCH 025/266] update docs to list supported responses/grants --- ...-Authentication-Clients-ResponsesGrants.md | 55 +++++++++++++++++++ .../OAuth-Authentication-Clients.md | 3 - .../OIDC-Authentication-Clients.md | 35 ++++++------ .../release_notes/RC6.md | 2 +- docs/cas-server-documentation/sidebar.md | 1 + .../support/oauth/OAuth20ResponseTypes.java | 5 +- ...onseTypeAuthorizationRequestValidator.java | 15 +++-- ...onseTypeAuthorizationRequestValidator.java | 6 +- ...onseTypeAuthorizationRequestValidator.java | 6 +- ...onseTypeAuthorizationRequestValidator.java | 6 +- ...ypeAuthorizationRequestValidatorTests.java | 2 +- 11 files changed, 101 insertions(+), 35 deletions(-) create mode 100644 docs/cas-server-documentation/authentication/OAuth-Authentication-Clients-ResponsesGrants.md diff --git a/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients-ResponsesGrants.md b/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients-ResponsesGrants.md new file mode 100644 index 000000000000..eb661707746e --- /dev/null +++ b/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients-ResponsesGrants.md @@ -0,0 +1,55 @@ +--- +layout: default +title: CAS - OAuth Authentication +category: Authentication +--- +{% include variables.html %} + + +# Client Registration - OAuth Authentication + +Every OAuth relying party must be defined as a CAS service: + +```json +{ + "@class" : "org.apereo.cas.support.oauth.services.OAuthRegisteredService", + "clientId": "clientid", + "clientSecret": "clientSecret", + "serviceId" : "^(https|imaps)://.*", + "name" : "OAuthService", + "id" : 100, + "supportedGrantTypes": [ "java.util.HashSet", [ "...", "..." ] ], + "supportedResponseTypes": [ "java.util.HashSet", [ "...", "..." ] ] +} +``` + +
:warning: Usage Warning!

CAS today does not strictly enforce +the collection of authorized supported response/grant types for backward compatibility reasons. This means that if left undefined, +all grant and response types may be allowed by the service definition and related policies. Do please note that this behavior +is subject to change in future releases and thus, it is strongly recommended that all authorized +grant/response types for each profile be declared in the service definition immediately to avoid surprises in the future.

+ +## Supported Grant Types + +The following grant types are supported by CAS: + +| Grant Type | +|------------------------------------------------| +| `urn:ietf:params:oauth:grant-type:device_code` | +| `authorization_code` | +| `password` | +| `client_credentials` | +| `refresh_token` | +| `urn:ietf:params:oauth:grant-type:uma-ticket` | + +## Supported Response Types + +The following response types are supported by CAS: + +| Grant Type | +|------------------| +| `code` | +| `token` | +| `device_code` | +| `id_token token` | +| `id_token` | diff --git a/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients.md b/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients.md index b1542a1295e4..9f945ca88e90 100644 --- a/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients.md +++ b/docs/cas-server-documentation/authentication/OAuth-Authentication-Clients.md @@ -49,9 +49,6 @@ a reference, this strategy would ultimately lead to poor upgrades increasing cha Service definitions are typically managed by the [service management](../services/Service-Management.html) facility. -
:warning: Usage Warning!

CAS today does not strictly enforce -the collection of authorized supported response/grant types for backward compatibility reasons. This means that if left undefined, all grant and response types may be allowed by the service definition and related policies. Do please note that this behavior is subject to change in future releases and thus, it is strongly recommended that all authorized grant/response types for each profile be declared in the service definition immediately to avoid surprises in the future.

- ## Encryptable Client Secrets Client secrets for OAuth relying parties may be defined as encrypted values prefixed with `{cas-cipher}`: diff --git a/docs/cas-server-documentation/authentication/OIDC-Authentication-Clients.md b/docs/cas-server-documentation/authentication/OIDC-Authentication-Clients.md index 6c0facd3e495..48670c292b23 100644 --- a/docs/cas-server-documentation/authentication/OIDC-Authentication-Clients.md +++ b/docs/cas-server-documentation/authentication/OIDC-Authentication-Clients.md @@ -9,6 +9,10 @@ category: Protocols Clients can be registered with CAS in the following ways. +Note that OpenID connect clients as service definitions are an +extension of [OAuth services](OAuth-Authentication-Clients.html) in CAS. All settings +that apply to an OAuth service definition should equally apply here as well. + ## Static Registration OpenID Connect clients can be *statically* registered with CAS as such: @@ -24,10 +28,6 @@ OpenID Connect clients can be *statically* registered with CAS as such: } ``` -Note that OpenID connect clients as service definitions are an -extension of [OAuth services](OAuth-Authentication-Clients.html) in CAS. All settings -that apply to an OAuth service definition should equally apply here as well. -
:information_source: Redirect URIs

Client application redirect URIs are specified using the serviceId field which supports regular expression patterns. If you need to support multiple URIs, you can try to OR them together or you may be able to construct the pattern that supports and matches all URIs with minor changes.

@@ -60,21 +60,18 @@ The following fields are specifically available for OpenID connect services: | `sectorIdentifierUri` | Optional. Host value of this URL is used as the sector identifier for the pairwise identifier calculation. If left undefined, the host value of the `serviceId` will be used instead. |
:information_source: Keep What You Need!

You are encouraged to -only keep and maintain properties and settings needed for a -particular integration. It is UNNECESSARY to grab a copy of all service fields and try to -configure them yet again based on their default. While -you may wish to keep a copy as a reference, this strategy would ultimately lead to poor -upgrades increasing chances of breaking changes and a messy -deployment at that.

- -Service definitions are typically managed and registered -with CAS by the [service management](../services/Service-Management.html) facility. - -
:warning: Usage Warning!

CAS today does not strictly -enforce the collection of authorized supported response/grant types for backward compatibility reasons if left blank. This means that if left -undefined, all grant and response types may be allowed by the service definition and related policies. Do please note that this behavior -is subject to change in future releases and thus, it is strongly recommended that all authorized grant/response types for -each profile be declared in the service definition immediately to avoid surprises in the future.

+only keep and maintain properties and settings needed for a particular integration. It is UNNECESSARY to grab a copy of all service fields and try to +configure them yet again based on their default. While you may wish to keep a copy as a reference, this strategy would ultimately lead to poor +upgrades increasing chances of breaking changes and a messy deployment at that.

+ +Service definitions are typically managed and registered with CAS by the [service management](../services/Service-Management.html) facility. + +## Response/Grant Types + +Supported responses and grant types can be authorized on a per-service basis. +[See this guide](OAuth-Authentication-Clients-ResponsesGrants.html) for more info. + +## Example An example registration record for an OpenID Connect relying party follows that allows the application with the redirect URI `https://app.example.org/oidc` to send authorization requests to CAS using the *authorization code* authentication flow. The registration record also instructs CAS to bypass the diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index f1150927fe4e..2802431b648a 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -52,7 +52,7 @@ Furthermore, sensible defaults would be used if grant types or response types ar ## Other Stuff -- Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io/docs/observation) and then reported as metrics. +- Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io) and then reported as metrics. - JSON and YAML service registries are able to auto-organize and store service definition files in dedicated directories identified by the service type. ## Library Upgrades diff --git a/docs/cas-server-documentation/sidebar.md b/docs/cas-server-documentation/sidebar.md index b23f6647ccca..3e2399b5753e 100644 --- a/docs/cas-server-documentation/sidebar.md +++ b/docs/cas-server-documentation/sidebar.md @@ -471,6 +471,7 @@ layout: null * [Refresh Token](/cas/{{ version }}/authentication/OAuth-ProtocolFlow-RefreshToken.html) * [ResourceOwner](/cas/{{ version }}/authentication/OAuth-ProtocolFlow-ResourceOwner.html) * [Clients](/cas/{{ version }}/authentication/OAuth-Authentication-Clients.html) + * [Response/Grant Types](/cas/{{ version }}/authentication/OAuth-Authentication-Clients-ResponsesGrants.html) * [CSRF](/cas/{{ version }}/authentication/OAuth-Authentication-CSRF.html) * [JWT Access Tokens](/cas/{{ version }}/authentication/OAuth-Authentication-JWT-AccessTokens.html) * [User Profiles](/cas/{{ version }}/authentication/OAuth-Authentication-UserProfiles.html) diff --git a/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/OAuth20ResponseTypes.java b/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/OAuth20ResponseTypes.java index dc2d15f2e739..332a82fc1fe0 100644 --- a/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/OAuth20ResponseTypes.java +++ b/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/OAuth20ResponseTypes.java @@ -31,12 +31,15 @@ public enum OAuth20ResponseTypes { * For implicit response type. */ IDTOKEN_TOKEN("id_token token"), + /** + * For implicit response type. + */ + TOKEN_IDTOKEN("token id_token"), /** * For implicit response type. */ ID_TOKEN("id_token"); - private final String type; OAuth20ResponseTypes(final String type) { diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator.java index 657f910db897..e4d589c56759 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator.java @@ -17,6 +17,8 @@ import org.pac4j.core.context.WebContext; import org.springframework.core.Ordered; +import java.util.EnumSet; + /** * This is {@link OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator}. * @@ -57,8 +59,13 @@ public boolean validate(final WebContext context) { @Override public boolean supports(final WebContext context) throws Exception { if (preValidate(context)) { - val responseType = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.RESPONSE_TYPE); - return OAuth20Utils.isResponseType(responseType.map(String::valueOf).orElse(StringUtils.EMPTY), getResponseType()); + val responseType = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.RESPONSE_TYPE) + .map(String::valueOf) + .orElse(StringUtils.EMPTY); + LOGGER.debug("Requested response type is [{}]", responseType); + return getSupportedResponseTypes() + .stream() + .anyMatch(allowedType -> OAuth20Utils.isResponseType(responseType, allowedType)); } return false; } @@ -68,7 +75,7 @@ public boolean supports(final WebContext context) throws Exception { * * @return the response type */ - public OAuth20ResponseTypes getResponseType() { - return OAuth20ResponseTypes.CODE; + public EnumSet getSupportedResponseTypes() { + return EnumSet.of(OAuth20ResponseTypes.CODE); } } diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenAndTokenResponseTypeAuthorizationRequestValidator.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenAndTokenResponseTypeAuthorizationRequestValidator.java index 0fe4bdc36c21..a0a672f45bc7 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenAndTokenResponseTypeAuthorizationRequestValidator.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenAndTokenResponseTypeAuthorizationRequestValidator.java @@ -7,6 +7,8 @@ import org.apereo.cas.support.oauth.OAuth20ResponseTypes; import org.apereo.cas.support.oauth.web.OAuth20RequestParameterResolver; +import java.util.EnumSet; + /** * This is {@link OAuth20IdTokenAndTokenResponseTypeAuthorizationRequestValidator}. @@ -25,7 +27,7 @@ public OAuth20IdTokenAndTokenResponseTypeAuthorizationRequestValidator( } @Override - public OAuth20ResponseTypes getResponseType() { - return OAuth20ResponseTypes.IDTOKEN_TOKEN; + public EnumSet getSupportedResponseTypes() { + return EnumSet.of(OAuth20ResponseTypes.IDTOKEN_TOKEN, OAuth20ResponseTypes.TOKEN_IDTOKEN); } } diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenResponseTypeAuthorizationRequestValidator.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenResponseTypeAuthorizationRequestValidator.java index 9fcb6380b958..172a7ddc04c8 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenResponseTypeAuthorizationRequestValidator.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20IdTokenResponseTypeAuthorizationRequestValidator.java @@ -7,6 +7,8 @@ import org.apereo.cas.support.oauth.OAuth20ResponseTypes; import org.apereo.cas.support.oauth.web.OAuth20RequestParameterResolver; +import java.util.EnumSet; + /** * This is {@link OAuth20IdTokenResponseTypeAuthorizationRequestValidator}. @@ -25,7 +27,7 @@ public OAuth20IdTokenResponseTypeAuthorizationRequestValidator( } @Override - public OAuth20ResponseTypes getResponseType() { - return OAuth20ResponseTypes.ID_TOKEN; + public EnumSet getSupportedResponseTypes() { + return EnumSet.of(OAuth20ResponseTypes.ID_TOKEN); } } diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20TokenResponseTypeAuthorizationRequestValidator.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20TokenResponseTypeAuthorizationRequestValidator.java index 6a54d09244fb..ac192160869b 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20TokenResponseTypeAuthorizationRequestValidator.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20TokenResponseTypeAuthorizationRequestValidator.java @@ -7,6 +7,8 @@ import org.apereo.cas.support.oauth.OAuth20ResponseTypes; import org.apereo.cas.support.oauth.web.OAuth20RequestParameterResolver; +import java.util.EnumSet; + /** * This is {@link OAuth20TokenResponseTypeAuthorizationRequestValidator}. @@ -25,7 +27,7 @@ public OAuth20TokenResponseTypeAuthorizationRequestValidator( } @Override - public OAuth20ResponseTypes getResponseType() { - return OAuth20ResponseTypes.TOKEN; + public EnumSet getSupportedResponseTypes() { + return EnumSet.of(OAuth20ResponseTypes.TOKEN); } } diff --git a/support/cas-server-support-oauth/src/test/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidatorTests.java b/support/cas-server-support-oauth/src/test/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidatorTests.java index 37936de7d0ae..68187418b2a0 100644 --- a/support/cas-server-support-oauth/src/test/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidatorTests.java +++ b/support/cas-server-support-oauth/src/test/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidatorTests.java @@ -174,7 +174,7 @@ public void verifyValidator() throws Exception { assertEquals(Ordered.LOWEST_PRECEDENCE, validator.getOrder()); assertNotNull(validator.getRegisteredServiceAccessStrategyEnforcer()); - assertEquals(OAuth20ResponseTypes.CODE, validator.getResponseType()); + assertTrue(validator.getSupportedResponseTypes().contains(OAuth20ResponseTypes.CODE)); assertNotNull(validator.getServicesManager()); assertNotNull(validator.getWebApplicationServiceServiceFactory()); } From 7a495ed399b31323e2dd8225e7efab94ab7e161a Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 11:15:57 +0400 Subject: [PATCH 026/266] additional settings to assist with Hazelcast aws discovery --- .../HazelcastAwsDiscoveryProperties.java | 43 +++++++++++++++++++ .../release_notes/RC6.md | 1 + .../cas/hz/HazelcastAwsDiscoveryStrategy.java | 16 ++++++- .../HazelcastAwsDiscoveryStrategyTests.java | 3 ++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/hazelcast/discovery/HazelcastAwsDiscoveryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/hazelcast/discovery/HazelcastAwsDiscoveryProperties.java index 90be1415b7fb..06f600de15bc 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/hazelcast/discovery/HazelcastAwsDiscoveryProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/hazelcast/discovery/HazelcastAwsDiscoveryProperties.java @@ -68,6 +68,32 @@ public class HazelcastAwsDiscoveryProperties implements Serializable { * AWS discovery HZ port property. */ public static final String AWS_DISCOVERY_PORT = "hz-port"; + /** + * Property name for connection and read timeouts when making a call to AWS API. + */ + public static final String AWS_DISCOVERY_CONNECTION_TIMEOUT = "connection-timeout-seconds"; + + /** + * Property name for connection and read timeouts when making a call to AWS API. + */ + public static final String AWS_DISCOVERY_READ_TIMEOUT = "read-timeout-seconds"; + + /** + * Property name for ECS cluster short name or ARN; default is the current cluster. + */ + public static final String AWS_DISCOVERY_CLUSTER = "cluster"; + + /** + * Property name for filter to look only for ECS tasks from the + * given service; mutually exclusive with {@link #AWS_DISCOVERY_FAMILY}. + */ + public static final String AWS_DISCOVERY_SERVCE_NAME = "service-name"; + + /** + * Property name for filter to look only for ECS tasks with the given family name; + * mutually exclusive with {@link #AWS_DISCOVERY_SERVCE_NAME}. + */ + public static final String AWS_DISCOVERY_FAMILY = "family"; @Serial private static final long serialVersionUID = -8281247687171101766L; @@ -136,4 +162,21 @@ public class HazelcastAwsDiscoveryProperties implements Serializable { * Its default value is 5. */ private int connectionTimeoutSeconds = 5; + + /** + * ECS cluster short name or ARN; default is the current cluster. + */ + private String cluster; + + /** + * Filter to look only for ECS tasks from the + * given service; mutually exclusive with {@link #getFamily()}. + */ + private String serviceName; + + /** + * Filter to look only for ECS tasks with the given family name; + * mutually exclusive with {@link #getServiceName()}. + */ + private String family; } diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index 2802431b648a..7188e8617fe5 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -54,6 +54,7 @@ Furthermore, sensible defaults would be used if grant types or response types ar - Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io) and then reported as metrics. - JSON and YAML service registries are able to auto-organize and store service definition files in dedicated directories identified by the service type. +- Support for additional settings such as `cluster`, `family`, etc to assist with Hazelcast discovery when CAS is deployed in AWS. ## Library Upgrades diff --git a/support/cas-server-support-hazelcast-discovery-aws/src/main/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategy.java b/support/cas-server-support-hazelcast-discovery-aws/src/main/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategy.java index 981ca6c156cd..aad52d271c1e 100644 --- a/support/cas-server-support-hazelcast-discovery-aws/src/main/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategy.java +++ b/support/cas-server-support-hazelcast-discovery-aws/src/main/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategy.java @@ -45,6 +45,12 @@ public Optional get(final HazelcastClusterProperties cl HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_PORT, Integer.toString(aws.getPort())); } + if (aws.getConnectionTimeoutSeconds() > 0) { + val timeout = Integer.toString(aws.getConnectionTimeoutSeconds()); + properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_CONNECTION_TIMEOUT, timeout); + properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_READ_TIMEOUT, timeout); + } + if (StringUtils.hasText(aws.getRegion())) { properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_REGION, aws.getRegion()); } @@ -57,7 +63,15 @@ public Optional get(final HazelcastClusterProperties cl if (StringUtils.hasText(aws.getTagValue())) { properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_TAG_VALUE, aws.getTagValue()); } - + if (StringUtils.hasText(aws.getCluster())) { + properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_CLUSTER, aws.getCluster()); + } + if (StringUtils.hasText(aws.getServiceName())) { + properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_SERVCE_NAME, aws.getServiceName()); + } + if (StringUtils.hasText(aws.getFamily())) { + properties.put(HazelcastAwsDiscoveryProperties.AWS_DISCOVERY_FAMILY, aws.getFamily()); + } return Optional.of(new DiscoveryStrategyConfig(new AwsDiscoveryStrategyFactory(), properties)); } diff --git a/support/cas-server-support-hazelcast-discovery-aws/src/test/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategyTests.java b/support/cas-server-support-hazelcast-discovery-aws/src/test/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategyTests.java index 78fee7be534c..d21e545b5881 100644 --- a/support/cas-server-support-hazelcast-discovery-aws/src/test/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategyTests.java +++ b/support/cas-server-support-hazelcast-discovery-aws/src/test/java/org/apereo/cas/hz/HazelcastAwsDiscoveryStrategyTests.java @@ -27,6 +27,9 @@ public void verifyAction() { val properties = new HazelcastClusterProperties(); val aws = properties.getDiscovery().getAws(); + aws.setFamily("Family"); + aws.setCluster("Cluster"); + aws.setServiceName("MyService"); aws.setAccessKey("AccessKey"); aws.setSecretKey("Secret"); aws.setIamRole("Role"); From eae626575354083104e6ad71e048fa58692939df Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 16:15:44 +0400 Subject: [PATCH 027/266] fix tests --- ...seRegisteredServiceUsernameAttributeProvider.java | 2 ++ ...ributeRegisteredServiceUsernameProviderTests.java | 12 ++++++------ .../integration/Configuring-SAML-SP-Integrations.md | 2 +- ...dcDefaultClientRegistrationRequestTranslator.java | 1 - 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java index de7bd2f32e06..2f6344151375 100644 --- a/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java +++ b/core/cas-server-core-services-api/src/main/java/org/apereo/cas/services/BaseRegisteredServiceUsernameAttributeProvider.java @@ -48,6 +48,8 @@ public abstract class BaseRegisteredServiceUsernameAttributeProvider implements @Override public final String resolveUsername(final RegisteredServiceUsernameProviderContext context) { + RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(context.getRegisteredService()); + val resolvedUsername = resolveUsernameInternal(context); if (canonicalizationMode == null) { canonicalizationMode = CaseCanonicalizationMode.NONE.name(); diff --git a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java index 41692561062e..1a879866cd31 100644 --- a/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java +++ b/core/cas-server-core-services/src/test/java/org/apereo/cas/services/PrincipalAttributeRegisteredServiceUsernameProviderTests.java @@ -131,16 +131,16 @@ public void verifyDisabledService() { attrs.put("userid", List.of("u1")); attrs.put("cn", List.of("TheName")); - val p = RegisteredServiceTestUtils.getPrincipal("person", attrs); + val principal = RegisteredServiceTestUtils.getPrincipal("person", attrs); - val service = RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService"); - service.setAccessStrategy(new DefaultRegisteredServiceAccessStrategy(false, false)); - service.setAttributeReleasePolicy(null); + val registeredService = RegisteredServiceTestUtils.getRegisteredService("usernameAttributeProviderService"); + registeredService.setAccessStrategy(new DefaultRegisteredServiceAccessStrategy(false, false)); + registeredService.setAttributeReleasePolicy(null); val usernameContext = RegisteredServiceUsernameProviderContext.builder() - .registeredService(service) + .registeredService(registeredService) .service(RegisteredServiceTestUtils.getService("usernameAttributeProviderService")) - .principal(p) + .principal(principal) .build(); assertThrows(UnauthorizedServiceException.class, () -> provider.resolveUsername(usernameContext)); } diff --git a/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md b/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md index c396ff42f99f..0b956dacc897 100644 --- a/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md +++ b/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md @@ -101,7 +101,7 @@ The following SAML SP integrations, as samples, are provided by CAS: - + diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java index 1ca16c62be7e..46d945016545 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java @@ -36,7 +36,6 @@ import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Optional; From 1eda0ab5cb2f30fec03362bfb852580e11168fda Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 17 Mar 2023 18:41:27 +0400 Subject: [PATCH 028/266] break down saml tests into more categories for attrs+response --- gradle/tests.gradle | 2 ++ .../saml/util/NonInflatingSaml20ObjectBuilderTests.java | 2 +- .../AttributeQueryAttributeReleasePolicyTests.java | 2 +- ...estRequestedAttributesAttributeReleasePolicyTests.java | 2 +- .../EduPersonTargetedIdAttributeReleasePolicyTests.java | 2 +- .../services/InCommonRSAttributeReleasePolicyTests.java | 2 +- ...tadataEntityAttributesAttributeReleasePolicyTests.java | 2 +- ...aRegistrationAuthorityAttributeReleasePolicyTests.java | 2 +- ...ataRequestedAttributesAttributeReleasePolicyTests.java | 2 +- ...atternMatchingEntityIdAttributeReleasePolicyTests.java | 2 +- .../services/RefedsRSAttributeReleasePolicyTests.java | 2 +- .../SamlRegisteredServiceAttributeReleasePolicyTests.java | 2 +- .../web/idp/profile/artifact/CasSamlArtifactMapTests.java | 8 +++++--- .../assertion/SamlProfileSamlAssertionBuilderTests.java | 2 +- .../builders/attr/SamlIdPAttributeDefinitionTests.java | 2 +- .../SamlProfileSamlAttributeStatementBuilderTests.java | 2 +- ...ProfileSamlRegisteredServiceAttributeBuilderTests.java | 2 +- .../SamlProfileAuthnContextClassRefBuilderTests.java | 2 +- .../authn/SamlProfileSamlAuthNStatementBuilderTests.java | 2 +- .../conditions/SamlProfileSamlConditionsBuilderTests.java | 2 +- .../nameid/SamlProfileSamlNameIdBuilderTests.java | 2 +- .../response/SamlProfileSaml2ResponseBuilderTests.java | 2 +- .../subject/SamlProfileSamlSubjectBuilderTests.java | 2 +- .../web/flow/SamlIdPConsentableAttributeBuilderTests.java | 2 +- .../saml/authentication/Saml20ObjectBuilderTests.java | 2 +- testcas.sh | 6 ++++++ 26 files changed, 36 insertions(+), 26 deletions(-) diff --git a/gradle/tests.gradle b/gradle/tests.gradle index 9bee5939c876..c623f4fe9ac8 100644 --- a/gradle/tests.gradle +++ b/gradle/tests.gradle @@ -81,6 +81,8 @@ enum TestCategories { SAMLMetadata, SAMLServiceProvider, SAMLLogout, + SAMLAttributes, + SAMLResponse, SCIM, SHELL, Simple, diff --git a/support/cas-server-support-saml-core/src/test/java/org/apereo/cas/support/saml/util/NonInflatingSaml20ObjectBuilderTests.java b/support/cas-server-support-saml-core/src/test/java/org/apereo/cas/support/saml/util/NonInflatingSaml20ObjectBuilderTests.java index ed6ae2d4dc29..443a5041d73b 100644 --- a/support/cas-server-support-saml-core/src/test/java/org/apereo/cas/support/saml/util/NonInflatingSaml20ObjectBuilderTests.java +++ b/support/cas-server-support-saml-core/src/test/java/org/apereo/cas/support/saml/util/NonInflatingSaml20ObjectBuilderTests.java @@ -40,7 +40,7 @@ * @author Misagh Moayyed * @since 6.2.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @SpringBootTest(classes = CoreSamlConfigurationTests.SharedTestConfiguration.class) public class NonInflatingSaml20ObjectBuilderTests { @Autowired diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AttributeQueryAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AttributeQueryAttributeReleasePolicyTests.java index ae154898313e..9e77b65ccc66 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AttributeQueryAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AttributeQueryAttributeReleasePolicyTests.java @@ -27,7 +27,7 @@ * @author Misagh Moayyed * @since 6.5.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata4" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AuthnRequestRequestedAttributesAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AuthnRequestRequestedAttributesAttributeReleasePolicyTests.java index c0b1f799bcaa..e96c0870afe1 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AuthnRequestRequestedAttributesAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/AuthnRequestRequestedAttributesAttributeReleasePolicyTests.java @@ -58,7 +58,7 @@ * @author Misagh Moayyed * @since 6.1.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.session-replication.cookie.auto-configure-cookie-path=true", "cas.authn.saml-idp.core.session-storage-type=TICKET_REGISTRY", diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/EduPersonTargetedIdAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/EduPersonTargetedIdAttributeReleasePolicyTests.java index dbede696d73a..0996a7d2b2b8 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/EduPersonTargetedIdAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/EduPersonTargetedIdAttributeReleasePolicyTests.java @@ -27,7 +27,7 @@ * @author Misagh Moayyed * @since 5.3.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata5" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/InCommonRSAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/InCommonRSAttributeReleasePolicyTests.java index d8dbc88fbce7..ca261d773d83 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/InCommonRSAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/InCommonRSAttributeReleasePolicyTests.java @@ -25,7 +25,7 @@ * @author Misagh Moayyed * @since 6.1.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata2" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataEntityAttributesAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataEntityAttributesAttributeReleasePolicyTests.java index f34d7f40f8cf..417286999415 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataEntityAttributesAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataEntityAttributesAttributeReleasePolicyTests.java @@ -26,7 +26,7 @@ * @author Misagh Moayyed * @since 6.5.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata2" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRegistrationAuthorityAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRegistrationAuthorityAttributeReleasePolicyTests.java index 4ff729585e5c..f60006d930c6 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRegistrationAuthorityAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRegistrationAuthorityAttributeReleasePolicyTests.java @@ -26,7 +26,7 @@ * @author Misagh Moayyed * @since 6.4.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata3" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRequestedAttributesAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRequestedAttributesAttributeReleasePolicyTests.java index 2b214eadac4c..22ad332e424d 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRequestedAttributesAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/MetadataRequestedAttributesAttributeReleasePolicyTests.java @@ -25,7 +25,7 @@ * @author Misagh Moayyed * @since 6.1.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata3" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/PatternMatchingEntityIdAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/PatternMatchingEntityIdAttributeReleasePolicyTests.java index e1d60496ddb6..e87e4439e060 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/PatternMatchingEntityIdAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/PatternMatchingEntityIdAttributeReleasePolicyTests.java @@ -25,7 +25,7 @@ * @author Misagh Moayyed * @since 5.3.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class PatternMatchingEntityIdAttributeReleasePolicyTests extends BaseSamlIdPConfigurationTests { diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/RefedsRSAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/RefedsRSAttributeReleasePolicyTests.java index 3bb4762378eb..a636a7e877bf 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/RefedsRSAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/RefedsRSAttributeReleasePolicyTests.java @@ -25,7 +25,7 @@ * @author Misagh Moayyed * @since 6.1.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") @TestPropertySource(properties = { "cas.authn.saml-idp.core.entity-id=https://cas.example.org/idp", "cas.authn.saml-idp.metadata.file-system.location=${#systemProperties['java.io.tmpdir']}/idp-metadata1" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/SamlRegisteredServiceAttributeReleasePolicyTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/SamlRegisteredServiceAttributeReleasePolicyTests.java index 9f41790ca9df..cf328a82744e 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/SamlRegisteredServiceAttributeReleasePolicyTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/services/SamlRegisteredServiceAttributeReleasePolicyTests.java @@ -32,7 +32,7 @@ * @author Misagh Moayyed * @since 6.2.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") public class SamlRegisteredServiceAttributeReleasePolicyTests { @Test public void verifyNoSamlService() { diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/artifact/CasSamlArtifactMapTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/artifact/CasSamlArtifactMapTests.java index 8e696c2bcd2b..c976263b34ef 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/artifact/CasSamlArtifactMapTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/artifact/CasSamlArtifactMapTests.java @@ -24,7 +24,7 @@ * @author Misagh Moayyed * @since 6.2.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @TestPropertySource(properties = "cas.tgc.crypto.enabled=false") public class CasSamlArtifactMapTests extends BaseSamlIdPConfigurationTests { @Test @@ -35,7 +35,8 @@ public void verifyOperationByParam() throws Exception { request.addParameter(casProperties.getTgc().getName(), tgt.getId()); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request, new MockHttpServletResponse())); - samlArtifactMap.put("artifact", "relying-party", "issuer", getAuthnRequestFor("example")); + val authnRequest = getAuthnRequestFor("example"); + samlArtifactMap.put("artifact", "relying-party", "issuer", authnRequest); assertTrue(samlArtifactMap.contains("artifact")); } @@ -54,7 +55,8 @@ public void verifyOperationByStore() throws Exception { profileManager.save(true, profile, false); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request, response)); - samlArtifactMap.put("artifact", "relying-party", "issuer", getAuthnRequestFor("example")); + val authnRequest = getAuthnRequestFor("example"); + samlArtifactMap.put("artifact", "relying-party", "issuer", authnRequest); assertTrue(samlArtifactMap.contains("artifact")); } } diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/assertion/SamlProfileSamlAssertionBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/assertion/SamlProfileSamlAssertionBuilderTests.java index 4e2a5d6b0b63..76ccdd1b8901 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/assertion/SamlProfileSamlAssertionBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/assertion/SamlProfileSamlAssertionBuilderTests.java @@ -28,7 +28,7 @@ * @author Misagh Moayyed * @since 6.4.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") public class SamlProfileSamlAssertionBuilderTests { @Nested diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlIdPAttributeDefinitionTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlIdPAttributeDefinitionTests.java index 5aa1a6d7136b..ac6421066420 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlIdPAttributeDefinitionTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlIdPAttributeDefinitionTests.java @@ -21,7 +21,7 @@ * @author Misagh Moayyed * @since 7.0.0 */ -@Tag("SAML2") +@Tag("SAMLAttributes") public class SamlIdPAttributeDefinitionTests extends BaseSamlIdPConfigurationTests { @Autowired @Qualifier(AttributeDefinitionStore.BEAN_NAME) diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlAttributeStatementBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlAttributeStatementBuilderTests.java index 412566e57859..694571121422 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlAttributeStatementBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlAttributeStatementBuilderTests.java @@ -30,7 +30,7 @@ * @author Misagh Moayyed * @since 6.4.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @TestPropertySource(properties = "cas.authn.attribute-repository.attribute-definition-store.json.location=classpath:/basic-definitions.json") public class SamlProfileSamlAttributeStatementBuilderTests extends BaseSamlIdPConfigurationTests { diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlRegisteredServiceAttributeBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlRegisteredServiceAttributeBuilderTests.java index 90068b603bf2..8b5e9b0046db 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlRegisteredServiceAttributeBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/attr/SamlProfileSamlRegisteredServiceAttributeBuilderTests.java @@ -26,7 +26,7 @@ * @author Misagh Moayyed * @since 6.0.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") public class SamlProfileSamlRegisteredServiceAttributeBuilderTests extends BaseSamlIdPConfigurationTests { @Autowired @Qualifier("samlProfileSamlAttributeStatementBuilder") diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileAuthnContextClassRefBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileAuthnContextClassRefBuilderTests.java index 803717d60559..f0d7c285c9ad 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileAuthnContextClassRefBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileAuthnContextClassRefBuilderTests.java @@ -27,7 +27,7 @@ * @author Misagh Moayyed * @since 6.2.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") public class SamlProfileAuthnContextClassRefBuilderTests { @Nested diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileSamlAuthNStatementBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileSamlAuthNStatementBuilderTests.java index 87a48899ee9e..e4cf5202f771 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileSamlAuthNStatementBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/authn/SamlProfileSamlAuthNStatementBuilderTests.java @@ -26,7 +26,7 @@ * @author Misagh Moayyed * @since 6.4.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") public class SamlProfileSamlAuthNStatementBuilderTests extends BaseSamlIdPConfigurationTests { @Autowired @Qualifier("samlProfileSamlAuthNStatementBuilder") diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/conditions/SamlProfileSamlConditionsBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/conditions/SamlProfileSamlConditionsBuilderTests.java index 0c10b86b11a3..1566dcfcbae8 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/conditions/SamlProfileSamlConditionsBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/conditions/SamlProfileSamlConditionsBuilderTests.java @@ -22,7 +22,7 @@ * @author Misagh Moayyed * @since 6.3.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @TestPropertySource(properties = { "cas.authn.saml-idp.response.skew-allowance=0", "cas.saml-core.skew-allowance=3000" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/nameid/SamlProfileSamlNameIdBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/nameid/SamlProfileSamlNameIdBuilderTests.java index c0114417c7df..0ed0a183b8f8 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/nameid/SamlProfileSamlNameIdBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/nameid/SamlProfileSamlNameIdBuilderTests.java @@ -38,7 +38,7 @@ * @author Misagh Moayyed * @since 5.3.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @SuppressWarnings("JavaUtilDate") public class SamlProfileSamlNameIdBuilderTests extends BaseSamlIdPConfigurationTests { @Autowired diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/response/SamlProfileSaml2ResponseBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/response/SamlProfileSaml2ResponseBuilderTests.java index c256369aceb1..9acb3d84d582 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/response/SamlProfileSaml2ResponseBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/response/SamlProfileSaml2ResponseBuilderTests.java @@ -39,7 +39,7 @@ * @author Misagh Moayyed * @since 5.3.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @TestPropertySource(properties = { "cas.tgc.crypto.enabled=false", "cas.authn.saml-idp.core.attribute-query-profile-enabled=true" diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/subject/SamlProfileSamlSubjectBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/subject/SamlProfileSamlSubjectBuilderTests.java index fe1f57682a0f..0c3b9af0c46c 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/subject/SamlProfileSamlSubjectBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/support/saml/web/idp/profile/builders/subject/SamlProfileSamlSubjectBuilderTests.java @@ -25,7 +25,7 @@ * @author Misagh Moayyed * @since 6.3.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") public class SamlProfileSamlSubjectBuilderTests extends BaseSamlIdPConfigurationTests { @Test diff --git a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/web/flow/SamlIdPConsentableAttributeBuilderTests.java b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/web/flow/SamlIdPConsentableAttributeBuilderTests.java index 598d7a7012a8..1cf0b7f4c41c 100644 --- a/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/web/flow/SamlIdPConsentableAttributeBuilderTests.java +++ b/support/cas-server-support-saml-idp/src/test/java/org/apereo/cas/web/flow/SamlIdPConsentableAttributeBuilderTests.java @@ -27,7 +27,7 @@ * @author Misagh Moayyed * @since 6.2.0 */ -@Tag("SAML2") +@Tag("SAMLResponse") @Import(CasConsentCoreConfiguration.class) @TestPropertySource(properties = "cas.authn.attribute-repository.attribute-definition-store.json.location=classpath:/basic-definitions.json") diff --git a/support/cas-server-support-saml/src/test/java/org/apereo/cas/support/saml/authentication/Saml20ObjectBuilderTests.java b/support/cas-server-support-saml/src/test/java/org/apereo/cas/support/saml/authentication/Saml20ObjectBuilderTests.java index 2f7cd6976e63..787c6184a1e1 100644 --- a/support/cas-server-support-saml/src/test/java/org/apereo/cas/support/saml/authentication/Saml20ObjectBuilderTests.java +++ b/support/cas-server-support-saml/src/test/java/org/apereo/cas/support/saml/authentication/Saml20ObjectBuilderTests.java @@ -16,7 +16,7 @@ * @author Jerome Leleu * @since 5.2.9 */ -@Tag("SAML2") +@Tag("SAMLResponse") public class Saml20ObjectBuilderTests extends AbstractOpenSamlTests { private static final String BASE64_SAML_AUTHN_REQUEST = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dG" diff --git a/testcas.sh b/testcas.sh index 6097bab3b853..dad5a315b3b2 100755 --- a/testcas.sh +++ b/testcas.sh @@ -298,6 +298,12 @@ while (( "$#" )); do saml2) task+="testSAML2 " ;; + samlresponse) + task+="testSAMLResponse " + ;; + samlattributes|samlattrs) + task+="testSAMLAttributes " + ;; saml) task+="testSAML " ;; From 2f70609b880b6f827a5da6d77f7cc5e2372575b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20LELEU?= Date: Fri, 17 Mar 2023 16:36:01 +0100 Subject: [PATCH 029/266] Expected PAR behavior --- .../oidc-par-authzcode-login/script.js | 93 +++++++++++++++++++ .../oidc-par-authzcode-login/script.json | 35 +++++++ .../services/Sample-1.json | 15 +++ 3 files changed, 143 insertions(+) create mode 100644 ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js create mode 100644 ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json create mode 100644 ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/services/Sample-1.json diff --git a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js new file mode 100644 index 000000000000..34a7d5c362b0 --- /dev/null +++ b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js @@ -0,0 +1,93 @@ +const puppeteer = require('puppeteer'); +const cas = require('../../cas.js'); +const assert = require('assert'); + +(async () => { + const browser = await puppeteer.launch(cas.browserOptions()); + const page = await cas.newPage(browser); + + await page.setRequestInterception(true); + + page.once("request", interceptedRequest => { + interceptedRequest.continue({ + 'method': 'POST', + 'postData': 'response_type=code&' + + 'client_id=client&scope=openid%20profile%20MyCustomScope&' + + 'redirect_uri=https://apereo.github.io&nonce=3d3a7457f9ad3&' + + 'state=1735fd6c43c14&claims=%7B%22userinfo%22%3A%20%7B%20%22name%22%3A%20%7B%22essential' + + '%22%3A%20true%7D%2C%22phone_number%22%3A%20%7B%22essential%22%3A%20true%7D%7D%7D&' + + 'client_secret=secret', + headers: { + ...interceptedRequest.headers(), + "Content-Type": "application/x-www-form-urlencoded" + } + }); + }); + + const response = await page.goto('https://localhost:8443/cas/oidc/oidcPushAuthorize'); + const responseBody = await response.text(); + const data = JSON.parse(responseBody); + const requestUri = data.request_uri; + await page.waitForTimeout(3000); + + page.setRequestInterception(false); + + const url = "https://localhost:8443/cas/oidc/oidcAuthorize?response_type=code" + + "&client_id=client&request_uri=" + requestUri; + + await cas.goto(page, url); + await page.waitForTimeout(3000); + await cas.loginWith(page, "casuser", "Mellon"); + + await page.waitForTimeout(3000); + + if (await cas.isVisible(page, "#allow")) { + await cas.click(page, "#allow"); + await page.waitForNavigation(); + } + + let code = await cas.assertParameter(page, "code"); + console.log(`Current code is ${code}`); + const accessTokenUrl = `https://localhost:8443/cas/oidc/token?grant_type=authorization_code` + + `&client_id=client&client_secret=secret&redirect_uri=https://apereo.github.io&code=${code}`; + await cas.goto(page, accessTokenUrl); + await page.waitForTimeout(3000); + let content = await cas.textContent(page, "body"); + const payload = JSON.parse(content); + assert(payload.access_token != null); + assert(payload.token_type != null); + assert(payload.expires_in != null); + assert(payload.scope != null); + + let decoded = await cas.decodeJwt(payload.id_token); + assert(decoded["sub"] === 'casuser'); + assert(decoded["client_id"] === 'client'); + assert(decoded["preferred_username"] === 'casuser'); + + assert(decoded["identity-name"] === undefined); + assert(decoded["common-name"] === undefined); + assert(decoded["lastname"] === undefined); + + assert(decoded["cn"] !== null); + assert(decoded["family_name"] !== null); + assert(decoded["name"] !== null); + + let profileUrl = `https://localhost:8443/cas/oidc/profile?access_token=${payload.access_token }`; + console.log(`Calling user profile ${profileUrl}`); + + await cas.doPost(profileUrl, "", { + 'Content-Type': "application/json" + }, res => { + assert(decoded["common-name"] === undefined); + assert(decoded["lastname"] === undefined); + + assert(res.data["cn"] != null); + assert(res.data["name"] != null); + assert(res.data["family_name"] != null); + assert(res.data.sub != null) + }, error => { + throw `Operation failed: ${error}`; + }); + + await browser.close(); +})(); diff --git a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json new file mode 100644 index 000000000000..ae565622a711 --- /dev/null +++ b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json @@ -0,0 +1,35 @@ +{ + "dependencies": "oidc", + "properties": [ + "--cas.server.name=https://localhost:8443", + "--cas.server.prefix=${cas.server.name}/cas", + + "--logging.level.org.apereo.cas=info", + + "--cas.audit.engine.enabled=false", + + "--cas.authn.attribute-repository.stub.attributes.common-name=casuser", + "--cas.authn.attribute-repository.stub.attributes.name=CAS", + "--cas.authn.attribute-repository.stub.attributes.lastname=Apereo", + "--cas.authn.attribute-repository.stub.attributes.identity-name=apereo-cas", + + "--cas.authn.oidc.core.issuer=https://localhost:8443/cas/oidc", + "--cas.authn.oidc.discovery.scopes=openid,profile,email,address,phone,MyCustomScope", + "--cas.authn.oidc.discovery.claims=sub,name,cn,given-name,given:name,family_name", + + "--cas.authn.oidc.core.user-defined-scopes.MyCustomScope=cn,given:name,name,family_name", + "--cas.authn.oidc.jwks.file-system.jwks-file=file:${#systemProperties['java.io.tmpdir']}/keystore.jwks", + + "--cas.authn.oidc.core.claims-map.cn=common-name", + "--cas.authn.oidc.core.claims-map.name=identity-name", + "--cas.authn.oidc.core.claims-map.family_name=lastname", + + "--cas.authn.oauth.core.user-profile-view-type=FLAT", + + "--cas.service-registry.core.init-from-json=true", + "--cas.service-registry.json.location=file:${PWD}/ci/tests/puppeteer/scenarios/${SCENARIO}/services" + ] +} + + + diff --git a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/services/Sample-1.json b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/services/Sample-1.json new file mode 100644 index 000000000000..32e4693c14f7 --- /dev/null +++ b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/services/Sample-1.json @@ -0,0 +1,15 @@ +{ + "@class": "org.apereo.cas.services.OidcRegisteredService", + "clientId": "client", + "clientSecret": "secret", + "serviceId": ".*", + "name": "Sample", + "id": 1, + "description": "Sample Service", + "evaluationOrder": 10000, + "informationUrl": "https://github.com/apereo/cas", + "privacyUrl": "https://github.com/apereo/cas", + "scopes" : [ "java.util.HashSet", [ "MyCustomScope", "openid", "profile" ] ], + "supportedGrantTypes": [ "java.util.HashSet", [ "authorization_code" ] ], + "supportedResponseTypes": [ "java.util.HashSet", [ "code" ] ] +} From 0b1f4da7df44d18c479901d49d0f2f3b177385ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Bodn=C3=A1r?= Date: Mon, 20 Mar 2023 06:16:35 +0100 Subject: [PATCH 030/266] docs: make javadocs of REST controllers reflect their actual content (#5616) Also make the javadocs more concise and fix the metadata of UserAuthenticationResource. --- .../rest/resources/ServiceTicketResource.java | 8 +------- .../resources/TicketGrantingTicketResource.java | 7 +------ .../rest/resources/TicketStatusResource.java | 8 +------- .../rest/resources/UserAuthenticationResource.java | 14 ++++---------- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java index 1a9c39fd7ac0..2630c85d5086 100644 --- a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java +++ b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java @@ -31,15 +31,9 @@ import java.util.Objects; /** - * {@link RestController} implementation of CAS' REST API. - *

- * This class implements main CAS RESTful resource for vending/deleting TGTs and vending STs: - *

+ * CAS RESTful resource for vending STs: *
    - *
  • {@code POST /v1/tickets}
  • *
  • {@code POST /v1/tickets/{TGT-id}}
  • - *
  • {@code GET /v1/tickets/{TGT-id}}
  • - *
  • {@code DELETE /v1/tickets/{TGT-id}}
  • *
* * @author Dmitriy Kopylenko diff --git a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java index 15353889f47b..91738c5fa400 100644 --- a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java +++ b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java @@ -33,14 +33,9 @@ import java.util.List; /** - * {@link RestController} implementation of CAS' REST API. - *

- * This class implements main CAS RESTful resource for vending/deleting TGTs and vending STs: - *

+ * CAS RESTful resource for vending and deleting TGTs: *
    *
  • {@code POST /v1/tickets}
  • - *
  • {@code POST /v1/tickets/{TGT-id}}
  • - *
  • {@code GET /v1/tickets/{TGT-id}}
  • *
  • {@code DELETE /v1/tickets/{TGT-id}}
  • *
* diff --git a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketStatusResource.java b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketStatusResource.java index b6baadbacc7f..a50add0c0140 100644 --- a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketStatusResource.java +++ b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketStatusResource.java @@ -16,15 +16,9 @@ import org.springframework.web.bind.annotation.RestController; /** - * {@link RestController} implementation of CAS' REST API. - *

- * This class implements main CAS RESTful resource for vending/deleting TGTs and vending STs: - *

+ * CAS RESTful resource validating TGTs: *
    - *
  • {@code POST /v1/tickets}
  • - *
  • {@code POST /v1/tickets/{TGT-id}}
  • *
  • {@code GET /v1/tickets/{TGT-id}}
  • - *
  • {@code DELETE /v1/tickets/{TGT-id}}
  • *
* * @author Dmitriy Kopylenko diff --git a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/UserAuthenticationResource.java b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/UserAuthenticationResource.java index cac8670aa7e6..e99c9e501e92 100644 --- a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/UserAuthenticationResource.java +++ b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/UserAuthenticationResource.java @@ -24,19 +24,13 @@ import javax.security.auth.login.FailedLoginException; /** - * {@link RestController} implementation of CAS' REST API. - *

- * This class implements main CAS RESTful resource for vending/deleting TGTs and vending STs: - *

+ * CAS RESTful resource for validating user credentials: *
    - *
  • {@code POST /v1/tickets}
  • - *
  • {@code POST /v1/tickets/{TGT-id}}
  • - *
  • {@code GET /v1/tickets/{TGT-id}}
  • - *
  • {@code DELETE /v1/tickets/{TGT-id}}
  • + *
  • {@code POST /v1/users}
  • *
* - * @author Dmitriy Kopylenko - * @since 4.1.0 + * @author Misagh Moayyed + * @since 6.1.0 */ @RestController("userAuthenticationResource") @Slf4j From 7d0574350a03fffde419e0ee86eff5828ee29026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Bodn=C3=A1r?= Date: Mon, 20 Mar 2023 06:16:55 +0100 Subject: [PATCH 031/266] docs: fix grammatical and name typos (#5617) --- README.md | 8 +++---- .../OIDC-Authentication-DPoP.md | 2 +- .../authentication/X509-Authentication.md | 2 +- .../Configuration-Management-Clustered.md | 2 +- ...n-Server-Management-SpringCloud-Default.md | 4 ++-- ...-Management-SpringCloud-HashiCorpConsul.md | 2 +- .../developer/Build-Process.md | 4 ++-- .../developer/Contributor-Guidelines.md | 8 +++---- .../protocol/CAS-Protocol-Specification.md | 24 +++++++++---------- .../protocol/CAS-Protocol-V2-Specification.md | 4 ++-- .../release_notes/RC4.md | 2 +- 11 files changed, 31 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 9a909b03e22b..b167a10b86b9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Additional resources are available as follows: ## Getting Started [![Maven Central](https://img.shields.io/maven-central/v/org.apereo.cas/cas-server-webapp?style=for-the-badge&logo=apachemaven)][casmavencentral] -[![Github Releases](https://img.shields.io/github/release/apereo/cas.svg?style=for-the-badge&logo=github)][githubreleases] +[![GitHub Releases](https://img.shields.io/github/release/apereo/cas.svg?style=for-the-badge&logo=github)][githubreleases] It is recommended to deploy CAS locally using the [WAR Overlay method][overlay]. Cloning or downloading the CAS codebase is **ONLY** required if you wish to contribute to the development of the project. @@ -64,11 +64,11 @@ The following features are supported by the CAS project: * OAuth v2 Protocol * OpenID Connect Protocol * WS-Federation Passive Requestor Protocol -* Authentication via JAAS, LDAP, RDBMS, X.509, Radius, SPNEGO, JWT, Remote, Apache Cassandra, Trusted, BASIC, Apache Shiro, MongoDb, Pac4J and more. +* Authentication via JAAS, LDAP, RDBMS, X.509, Radius, SPNEGO, JWT, Remote, Apache Cassandra, Trusted, BASIC, Apache Shiro, MongoDB, Pac4J and more. * Delegated authentication to WS-FED, Facebook, Twitter, SAML IdP, OpenID Connect, CAS and more. * Authorization via ABAC, Time/Date, REST, Internet2's Grouper and more. -* HA clustered deployments via Hazelcast, JPA, Apache Cassandra, Memcached, Apache Ignite, MongoDb, Redis, DynamoDb, and more. -* Application registration backed by JSON, LDAP, YAML, Apache Cassandra, JPA, MongoDb, DynamoDb, Redis and more. +* HA clustered deployments via Hazelcast, JPA, Apache Cassandra, Memcached, Apache Ignite, MongoDB, Redis, DynamoDb, and more. +* Application registration backed by JSON, LDAP, YAML, Apache Cassandra, JPA, MongoDB, DynamoDb, Redis and more. * Multifactor authentication via Duo Security, YubiKey, RSA, Google Authenticator, U2F, WebAuthn and more. * Administrative UIs to manage logging, monitoring, statistics, configuration, client registration and more. * Global and per-application user interface theme and branding. diff --git a/docs/cas-server-documentation/authentication/OIDC-Authentication-DPoP.md b/docs/cas-server-documentation/authentication/OIDC-Authentication-DPoP.md index e5b39d0fa516..e0088462708a 100644 --- a/docs/cas-server-documentation/authentication/OIDC-Authentication-DPoP.md +++ b/docs/cas-server-documentation/authentication/OIDC-Authentication-DPoP.md @@ -23,7 +23,7 @@ The SPA authentication flow with a DPoP token can be summarized as such: - The SPA generates a new RSA or EC key pair in such a way so the private key parameters cannot be exported from the browser. - To request a DPoP access token the SPA generates a one-time-use JWT signed with the private key. The function of this JWT is to demonstrate possession of the key. Its header includes the public parameters of the signing key in JWK format. -- The SPA makes the usual token request to CAS but to trigger issue of a DPoP access token the proof JWT must be included in a HTTP request header called *DPoP*. +- The SPA makes the usual token request to CAS but to trigger issue of a DPoP access token the proof JWT must be included in an HTTP request header called *DPoP*. - If the DPoP proof is valid and signed with a supported JWS algorithms the token response will appear in the usual format, but with the token type set to *DPoP*. To access a protected resource with a DPoP token (such as the `profile` endpoint in CAS) the client needs diff --git a/docs/cas-server-documentation/authentication/X509-Authentication.md b/docs/cas-server-documentation/authentication/X509-Authentication.md index 47aaae10a1a8..6c3f16474be1 100644 --- a/docs/cas-server-documentation/authentication/X509-Authentication.md +++ b/docs/cas-server-documentation/authentication/X509-Authentication.md @@ -97,7 +97,7 @@ acceptable client certificates. These settings can be used to turn on and configure CAS to extract an X509 certificate from a base64 encoded certificate -on a HTTP request header (placed there by a proxy in front of CAS). +on an HTTP request header (placed there by a proxy in front of CAS). If this is set to true, it is important that the proxy cannot be bypassed by users and that the proxy ensures the header never originates from the browser. diff --git a/docs/cas-server-documentation/configuration/Configuration-Management-Clustered.md b/docs/cas-server-documentation/configuration/Configuration-Management-Clustered.md index c29f732c6fa5..111d50f13071 100644 --- a/docs/cas-server-documentation/configuration/Configuration-Management-Clustered.md +++ b/docs/cas-server-documentation/configuration/Configuration-Management-Clustered.md @@ -20,7 +20,7 @@ If CAS nodes are not sharing a central location for configuration properties suc node contains a copy of the settings, any changes you make to one node must be replicated and synced across all nodes so they are persisted on disk. The broadcast mechanism noted above only applies changes to the runtime and the running CAS instance. Ideally, you should be keeping track -of CAS settings in a shared (git) repository (or better yet, inside a private Github repository perhaps) +of CAS settings in a shared (git) repository (or better yet, inside a private GitHub repository perhaps) where you make a change in one place and it's broadcasted to all nodes. This model removes the need for synchronizing changes across disks and CAS nodes.CAS uses the Spring Cloud Bus to manage configuration in a distributed deployment. Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. diff --git a/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-Default.md b/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-Default.md index 03fbf2142e5c..66a408300092 100644 --- a/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-Default.md +++ b/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-Default.md @@ -9,7 +9,7 @@ category: Configuration # Spring Cloud Configuration Server - Spring Cloud Default The Spring Cloud Configuration Server is able to handle `git` or `svn` based repositories that host CAS configuration. -Such repositories can either be local to the deployment, or they could be on the cloud in form of GitHub/BitBucket. Access to +Such repositories can either be local to the deployment, or they could be on the cloud in form of GitHub/Bitbucket. Access to cloud-based repositories can either be in form of a username/password, or via SSH so as long the appropriate keys are configured in the CAS deployment environment which is really no different than how one would normally access a git repository via SSH. @@ -44,5 +44,5 @@ thirdPartyStartsWith="spring.cloud.config.server.git" thirdPartyExactMatch="spring.profiles.active" %} -The above configuration also applies to online git-based repositories such as Github, BitBucket, etc. +The above configuration also applies to online git-based repositories such as GitHub, Bitbucket, etc. diff --git a/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-HashiCorpConsul.md b/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-HashiCorpConsul.md index 6d236b6b399e..7e7624156311 100644 --- a/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-HashiCorpConsul.md +++ b/docs/cas-server-documentation/configuration/Configuration-Server-Management-SpringCloud-HashiCorpConsul.md @@ -23,7 +23,7 @@ config/application/ The most specific property source is at the top, with the least specific at the bottom. Properties in the `config/application` folder are applicable to all applications using consul for configuration. Properties in the `config/cas` folder are only available to the instances of the service named `cas`. -Configuration is currently read on startup of the application. Sending a HTTP POST to `/refresh` will cause the configuration to be reloaded. Watching the key value store (which Consul supports) is not currently possible, but will be a future addition to this project. +Configuration is currently read on startup of the application. Sending an HTTP POST to `/refresh` will cause the configuration to be reloaded. Watching the key value store (which Consul supports) is not currently possible, but will be a future addition to this project. The Consul Config Watch takes advantage of the ability of consul to [watch a key prefix](https://www.consul.io/docs/agent). The Config Watch makes a blocking Consul HTTP API call to determine if any relevant configuration data has changed for the current application. If there is new configuration data a `Refresh Event` is published. This is equivalent to calling the `/refresh` Spring Boot actuator endpoint. diff --git a/docs/cas-server-documentation/developer/Build-Process.md b/docs/cas-server-documentation/developer/Build-Process.md index e7327f4ee4b2..ed5980388c6f 100644 --- a/docs/cas-server-documentation/developer/Build-Process.md +++ b/docs/cas-server-documentation/developer/Build-Process.md @@ -31,7 +31,7 @@ git clone --recursive --depth=1 --single-branch --branch=master git@github.com:a # git fetch --unshallow ``` -For a successful clone, you will need to have set up SSH keys for your account on Github. +For a successful clone, you will need to have set up SSH keys for your account on GitHub. If that is not an option, you may clone the CAS repository under `https` via `https://github.com/apereo/cas.git`. You may also need to update submodules linked to the CAS repository. Newer versions of Git will do this automatically, @@ -186,7 +186,7 @@ cd cas-server ./gradlew eclipse ``` -Then, import the project into eclipse using "General\Existing Projects into Workspace" +Then, import the project into Eclipse using "General\Existing Projects into Workspace" and choose "Add Gradle Nature" from the "Configure" context menu of the project.
:warning: YMMV

We have had a less than ideal experience with Eclipse and its support for Gradle-based diff --git a/docs/cas-server-documentation/developer/Contributor-Guidelines.md b/docs/cas-server-documentation/developer/Contributor-Guidelines.md index 58fc614ab710..c2b69ce715d3 100644 --- a/docs/cas-server-documentation/developer/Contributor-Guidelines.md +++ b/docs/cas-server-documentation/developer/Contributor-Guidelines.md @@ -135,7 +135,7 @@ you for longer prosperity. Be not afraid; the worst that could happen is someone ## How do I know who's working on what? -- Follow the *WIP Pattern* and submit an early pull requests in Draft status. This is the recommended strategy from Github: +- Follow the *WIP Pattern* and submit an early pull requests in Draft status. This is the recommended strategy from GitHub: > Pull Requests are a great way to start a conversation of a feature, so start one as soon as possible- > even before you are finished with the code. Your team can comment on the feature as it evolves, @@ -199,7 +199,7 @@ share your use case and ideas with others and brainstorm about variations and po often help clear the path to better and more objective solutions. That said, if you are specifically looking for an idea repository where you would log an idea or feature request for someone else to come along and spend time, money and energy to review and provide a solution or enhancement for you, that place does not exist with the CAS project. As was noted earlier, -if you would like to see a enhancement in CAS, you are to either study, learn and do the work yourself and contribute that back +if you would like to see an enhancement in CAS, you are to either study, learn and do the work yourself and contribute that back to the CAS project after having had the proper discussions with the wider developer community, or you can provide funding for the work or contract with someone so they can do the work on your behalf. There are no other viable, sustainable options. @@ -290,13 +290,13 @@ Before you do anything else, make sure you have a [functional build](Build-Proce To successfully finish this exercise you need: 1. [Git](https://git-scm.com/downloads) -2. [IntelliJ IDEA](https://www.jetbrains.com/idea/download/), eclipse or NetBeans (Depending on the change, `vim` may be perfectly fine too) +2. [IntelliJ IDEA](https://www.jetbrains.com/idea/download/), Eclipse or NetBeans (Depending on the change, `vim` may be perfectly fine too) 3. [Java (JDK)](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) ### Fork the repository First thing you need to do is to fork the CAS repository under your own account. The -CAS repository is hosted on Github and is available [here](https://github.com/apereo/cas). +CAS repository is hosted on GitHub and is available [here](https://github.com/apereo/cas). ### Clone Repositories diff --git a/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md b/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md index ca38d1570bfe..b0eda920184e 100644 --- a/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md +++ b/docs/cas-server-documentation/protocol/CAS-Protocol-Specification.md @@ -50,7 +50,7 @@ application. **1.1. Conventions & Definitions** ---------------------------------- -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119[[1](<#1>)]. @@ -128,7 +128,7 @@ MUST be handled by `/login`. - `service` [OPTIONAL] - the identifier of the application the client is trying to access. In almost all cases, this will be the URL of the - application. As a HTTP request parameter, this URL value MUST be + application. As an HTTP request parameter, this URL value MUST be URL-encoded as described in section 2.2 of RFC 3986 [[4](<#4>)]. If a `service` is not specified and a single sign-on session does not yet exist, CAS SHOULD request credentials from the user to initiate a single @@ -261,7 +261,7 @@ as a credential acceptor. They are all case-sensitive and they all MUST be handled by `/login`. - `service` [OPTIONAL] - the URL of the application the client is trying to - access. As a HTTP request parameter, this URL value MUST be URL-encoded as + access. As an HTTP request parameter, this URL value MUST be URL-encoded as described in Section 2.2 of RFC 1738 [[4](<#4>)]. CAS MUST redirect the client to this URL upon successful authentication. This is discussed in detail in Section [2.2.4](#head2.2.4). If the CAS Server operates in @@ -363,7 +363,7 @@ sensitive and SHOULD be handled by `/logout`. browser might be automatically redirected to the URL specified by `service` after the logout was performed by the CAS server. If redirection by the CAS Server is actually performed depends on the server configuration. - As a HTTP request parameter, the `service` value MUST be URL-encoded as + As an HTTP request parameter, the `service` value MUST be URL-encoded as described in Section 2.2 of RFC 1738 [[4](<#4>)]. > Note: It is STRONGLY RECOMMENDED that all `service` urls be filtered via @@ -408,7 +408,7 @@ after successful logout. The CAS Server MAY support Single Logout (SLO). SLO means that the user gets logged out not only from the CAS Server, but also from all visited CAS client -applications. If SLO is supported by the CAS Server, the CAS Server MUST send a +applications. If SLO is supported by the CAS Server, the CAS Server MUST send an HTTP POST request containing a logout XML document (see [Appendix C](<#head_appdx_c>)) to all service URLs provided to CAS during this CAS session whenever a Ticket Granting Ticket is explicitly expired by the user (e.g. during logout). @@ -435,7 +435,7 @@ availability ("fire and forget"). Handling the logout POST request data is up to the CAS client. It is RECOMMENDED to logout the user from the application identified by the service ticket id sent in the SLO POST request. -If the client supports SLO POST request handling, the client SHALL return a HTTP success +If the client supports SLO POST request handling, the client SHALL return an HTTP success status code. @@ -460,7 +460,7 @@ case sensitive and MUST all be handled by `/validate`. - `service` [REQUIRED] - the identifier of the service for which the ticket was issued, as discussed in Section 2.2.1. - As a HTTP request parameter, the `service` value MUST be URL-encoded as + As an HTTP request parameter, the `service` value MUST be URL-encoded as described in Section 2.2 of RFC 1738 [[4](<#4>)]. > Note: It is STRONGLY RECOMMENDED that all `service` urls be filtered via @@ -535,7 +535,7 @@ are case sensitive and MUST all be handled by `/serviceValidate`. - `service` [REQUIRED] - the identifier of the service for which the ticket was issued, as discussed in Section [2.2.1](#head2.2.1). - As a HTTP request parameter, the `service` value MUST be URL-encoded as + As an HTTP request parameter, the `service` value MUST be URL-encoded as described in Section 2.2 of RFC 1738 [[4](<#4>)]. > Note: It is STRONGLY RECOMMENDED that all `service` urls be filtered via @@ -552,7 +552,7 @@ are case sensitive and MUST all be handled by `/serviceValidate`. - `pgtUrl` [OPTIONAL] - the URL of the proxy callback. Discussed in Section [2.5.4](#head2.5.4). - As a HTTP request parameter, the "pgtUrl" value MUST be URL-encoded as + As an HTTP request parameter, the "pgtUrl" value MUST be URL-encoded as described in Section 2.2 of RFC 1738 [[4](<#4>)]. - `renew` [OPTIONAL] - if this parameter is set, ticket validation will only @@ -898,7 +898,7 @@ case-sensitive. service ticket or proxy ticket validation. - `targetService` [REQUIRED] - the service identifier of the back-end service. Note that not all back-end services are web services so this service identifier - will not always be an URL. However, the service identifier specified here + will not always be a URL. However, the service identifier specified here MUST match the `service` parameter specified to `/proxyValidate` upon validation of the proxy ticket. @@ -1362,7 +1362,7 @@ The Long-Term Ticket Granting Ticket lifetime MAY not exceed 3 months. ------------------------------- `/samlValidate` checks the validity of a Service Ticket by a SAML 1.1 request -document provided by a HTTP POST. A SAML (Secure Access Markup Language)[[7](#7)] 1.1 +document provided by an HTTP POST. A SAML (Secure Access Markup Language)[[7](#7)] 1.1 response document MUST be returned. This allows the release of additional information (attributes) of the authenticated NetID. The Security Assertion Markup Language (SAML) describes a document and protocol framework by which @@ -1391,7 +1391,7 @@ are both case-sensitive. ### **4.2.2 HTTP Request Method and Body** -Request to /samlValidate MUST be a HTTP POST request. The request body MUST be a valid +Request to /samlValidate MUST be an HTTP POST request. The request body MUST be a valid SAML 1.0 or 1.1 request XML document of document type "text/xml". diff --git a/docs/cas-server-documentation/protocol/CAS-Protocol-V2-Specification.md b/docs/cas-server-documentation/protocol/CAS-Protocol-V2-Specification.md index 2afc97e3e3d3..45c7ef65407f 100644 --- a/docs/cas-server-documentation/protocol/CAS-Protocol-V2-Specification.md +++ b/docs/cas-server-documentation/protocol/CAS-Protocol-V2-Specification.md @@ -24,7 +24,7 @@ Copyright © 2005, Yale University This is the official specification of the CAS 1.0 and 2.0 protocols. It is subject to change. ## 1.1. Conventions & Definitions -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119[1]. * "Client" refers to the end user and/or the web browser. @@ -61,7 +61,7 @@ to present credentials regardless of the existence of a single sign-on session w with the "gateway" parameter. Services redirecting to the */login* URI and login form views posting to the */login* URI SHOULD NOT set both the "renew" and "gateway" request parameters. Behavior is undefined if both are set. It is RECOMMENDED that CAS implementations ignore the "gateway" parameter if "renew" is set. It is RECOMMENDED that when the renew parameter -is set itsvalue be "true". +is set, its value be "true". 3. `gateway [OPTIONAL]` - if this parameter is set, CAS will not ask the client for credentials. If the client has a pre-existing single sign-on session with CAS, or if a single sign-on session can be established through non-interactive means (i.e. trust authentication), CAS MAY redirect the client to the URL specified by the "service" parameter, appending a valid diff --git a/docs/cas-server-documentation/release_notes/RC4.md b/docs/cas-server-documentation/release_notes/RC4.md index 796e618af379..23b84442ef7f 100644 --- a/docs/cas-server-documentation/release_notes/RC4.md +++ b/docs/cas-server-documentation/release_notes/RC4.md @@ -35,7 +35,7 @@ maintenance and release planning, especially when it comes to addressing critica ## System Requirements The JDK baseline requirement for this CAS release is and **MUST** be JDK `17`. All compatible distributions -such as Amazon Corretto, Zulu, eclipse Temurin, etc should work and are implicitly supported. +such as Amazon Corretto, Zulu, Eclipse Temurin, etc should work and are implicitly supported. ## New & Noteworthy From 42bb6e5ed2399f5428c264bbc3cffcf04d721ad8 Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 09:40:09 -0500 Subject: [PATCH 032/266] test: Create a failing test to illustrate the issue of not closing stream Made a failing test. --- .../mongo/MongoDbCasEventRepositoryTests.java | 106 ++++++++++++++++-- 1 file changed, 94 insertions(+), 12 deletions(-) diff --git a/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java b/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java index 20630a450ebb..f45ba0177ddf 100644 --- a/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java +++ b/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java @@ -1,17 +1,36 @@ package org.apereo.cas.support.events.mongo; + + import org.apereo.cas.config.CasCoreHttpConfiguration; import org.apereo.cas.config.MongoDbEventsConfiguration; +import org.apereo.cas.mock.MockTicketGrantingTicket; +import org.apereo.cas.support.events.AbstractCasEvent; import org.apereo.cas.support.events.AbstractCasEventRepositoryTests; import org.apereo.cas.support.events.CasEventRepository; +import org.apereo.cas.support.events.dao.CasEvent; +import org.apereo.cas.support.events.ticket.CasTicketGrantingTicketCreatedEvent; +import org.apereo.cas.util.DateTimeUtils; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; import lombok.Getter; +import lombok.val; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; +import org.springframework.data.mongodb.core.MongoTemplate; +import java.time.Instant; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Test cases for {@link MongoDbCasEventRepository}. @@ -21,24 +40,87 @@ */ @Tag("MongoDb") @SpringBootTest(classes = { - MongoDbEventsConfiguration.class, - CasCoreHttpConfiguration.class, - RefreshAutoConfiguration.class + MongoDbEventsConfiguration.class, + CasCoreHttpConfiguration.class, + RefreshAutoConfiguration.class }, - properties = { - "cas.events.mongo.user-id=root", - "cas.events.mongo.password=secret", - "cas.events.mongo.host=localhost", - "cas.events.mongo.port=27017", - "cas.events.mongo.authentication-database-name=admin", - "cas.events.mongo.database-name=events", - "cas.events.mongo.drop-collection=true" - }) + properties = { + "cas.events.mongo.user-id=root", + "cas.events.mongo.password=secret", + "cas.events.mongo.host=localhost", + "cas.events.mongo.port=27017", + "cas.events.mongo.authentication-database-name=admin", + "cas.events.mongo.database-name=events", + "cas.events.mongo.drop-collection=true" + }) @Getter @EnabledIfListeningOnPort(port = 27017) public class MongoDbCasEventRepositoryTests extends AbstractCasEventRepositoryTests { + private static final int NUM_OF_EVENTS_LARGER_THAN_MIN_BATCH_SIZE = 103; + @Autowired @Qualifier(CasEventRepository.BEAN_NAME) private CasEventRepository eventRepository; + + @Autowired + @Qualifier("mongoEventsTemplate") + private MongoTemplate mongoTemplate; + + private long currentCount; + + + @BeforeEach + public void setup() throws Exception { + currentCount = getOpenCursorCount(); + val tgt = new MockTicketGrantingTicket("casuser"); + val event = new CasTicketGrantingTicketCreatedEvent(this, tgt, null); + for (var x = 0; x < NUM_OF_EVENTS_LARGER_THAN_MIN_BATCH_SIZE; x++) { + val dto = prepareCasEvent(event); + dto.setCreationTime(event.getTicketGrantingTicket().getCreationTime().toString()); + dto.putEventId(event.getTicketGrantingTicket().getId()); + dto.setPrincipalId(event.getTicketGrantingTicket().getAuthentication().getPrincipal().getId()); + eventRepository.save(dto); + } + } + + @Test + public void makeSureCursorsGetClosed() throws Exception { + val stream = eventRepository.load(); + assertNotNull(stream); + val noValues = stream.findAny().isEmpty(); + assertFalse(noValues); + assertEquals(currentCount, getOpenCursorCount()); + + } + + @Test + public void makeSureCursorsGetClosedIterateThroughStream() throws Exception { + val stream = eventRepository.load(); + assertNotNull(stream); + val aList = stream.collect(Collectors.toList()); + assertTrue(!aList.isEmpty()); + assertEquals(currentCount, getOpenCursorCount()); + + } + + private CasEvent prepareCasEvent(final AbstractCasEvent event) { + val dto = new CasEvent(); + dto.setType(event.getClass().getCanonicalName()); + dto.putTimestamp(event.getTimestamp()); + val dt = DateTimeUtils.zonedDateTimeOf(Instant.ofEpochMilli(event.getTimestamp())); + dto.setCreationTime(dt.toString()); + return dto; + } + + public long getOpenCursorCount() { + var cmd = new Document("serverStatus", 1); + cmd.append("metrics", true); + cmd.append("cursor", true); + var result = mongoTemplate.executeCommand(cmd); + var open = (Document) result.get("metrics", Document.class).get("cursor", Document.class).get("open", Document.class); + return open.getLong("total"); + } + + } From 133be4b2d42174d8f62a5cbfdc0455fcacf407cb Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 09:43:03 -0500 Subject: [PATCH 033/266] test: Fix failing test Fixed failing test by using try-with-resources on stream. --- .../events/mongo/MongoDbCasEventRepositoryTests.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java b/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java index f45ba0177ddf..60d0fdf23c24 100644 --- a/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java +++ b/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java @@ -86,10 +86,11 @@ public void setup() throws Exception { @Test public void makeSureCursorsGetClosed() throws Exception { - val stream = eventRepository.load(); - assertNotNull(stream); - val noValues = stream.findAny().isEmpty(); - assertFalse(noValues); + try (val stream = eventRepository.load()) { + assertNotNull(stream); + val noValues = stream.findAny().isEmpty(); + assertFalse(noValues); + } assertEquals(currentCount, getOpenCursorCount()); } From 831dbe72937a3dafaa660166597799bd92f1003a Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 09:52:12 -0500 Subject: [PATCH 034/266] test: removed tests created for demo purposes --- .../mongo/MongoDbCasEventRepositoryTests.java | 107 ++---------------- 1 file changed, 12 insertions(+), 95 deletions(-) diff --git a/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java b/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java index 60d0fdf23c24..20630a450ebb 100644 --- a/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java +++ b/support/cas-server-support-events-mongo/src/test/java/org/apereo/cas/support/events/mongo/MongoDbCasEventRepositoryTests.java @@ -1,36 +1,17 @@ package org.apereo.cas.support.events.mongo; - - import org.apereo.cas.config.CasCoreHttpConfiguration; import org.apereo.cas.config.MongoDbEventsConfiguration; -import org.apereo.cas.mock.MockTicketGrantingTicket; -import org.apereo.cas.support.events.AbstractCasEvent; import org.apereo.cas.support.events.AbstractCasEventRepositoryTests; import org.apereo.cas.support.events.CasEventRepository; -import org.apereo.cas.support.events.dao.CasEvent; -import org.apereo.cas.support.events.ticket.CasTicketGrantingTicketCreatedEvent; -import org.apereo.cas.util.DateTimeUtils; import org.apereo.cas.util.junit.EnabledIfListeningOnPort; import lombok.Getter; -import lombok.val; -import org.bson.Document; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.data.mongodb.core.MongoTemplate; -import java.time.Instant; -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; /** * Test cases for {@link MongoDbCasEventRepository}. @@ -40,88 +21,24 @@ */ @Tag("MongoDb") @SpringBootTest(classes = { - MongoDbEventsConfiguration.class, - CasCoreHttpConfiguration.class, - RefreshAutoConfiguration.class + MongoDbEventsConfiguration.class, + CasCoreHttpConfiguration.class, + RefreshAutoConfiguration.class }, - properties = { - "cas.events.mongo.user-id=root", - "cas.events.mongo.password=secret", - "cas.events.mongo.host=localhost", - "cas.events.mongo.port=27017", - "cas.events.mongo.authentication-database-name=admin", - "cas.events.mongo.database-name=events", - "cas.events.mongo.drop-collection=true" - }) + properties = { + "cas.events.mongo.user-id=root", + "cas.events.mongo.password=secret", + "cas.events.mongo.host=localhost", + "cas.events.mongo.port=27017", + "cas.events.mongo.authentication-database-name=admin", + "cas.events.mongo.database-name=events", + "cas.events.mongo.drop-collection=true" + }) @Getter @EnabledIfListeningOnPort(port = 27017) public class MongoDbCasEventRepositoryTests extends AbstractCasEventRepositoryTests { - private static final int NUM_OF_EVENTS_LARGER_THAN_MIN_BATCH_SIZE = 103; - @Autowired @Qualifier(CasEventRepository.BEAN_NAME) private CasEventRepository eventRepository; - - @Autowired - @Qualifier("mongoEventsTemplate") - private MongoTemplate mongoTemplate; - - private long currentCount; - - - @BeforeEach - public void setup() throws Exception { - currentCount = getOpenCursorCount(); - val tgt = new MockTicketGrantingTicket("casuser"); - val event = new CasTicketGrantingTicketCreatedEvent(this, tgt, null); - for (var x = 0; x < NUM_OF_EVENTS_LARGER_THAN_MIN_BATCH_SIZE; x++) { - val dto = prepareCasEvent(event); - dto.setCreationTime(event.getTicketGrantingTicket().getCreationTime().toString()); - dto.putEventId(event.getTicketGrantingTicket().getId()); - dto.setPrincipalId(event.getTicketGrantingTicket().getAuthentication().getPrincipal().getId()); - eventRepository.save(dto); - } - } - - @Test - public void makeSureCursorsGetClosed() throws Exception { - try (val stream = eventRepository.load()) { - assertNotNull(stream); - val noValues = stream.findAny().isEmpty(); - assertFalse(noValues); - } - assertEquals(currentCount, getOpenCursorCount()); - - } - - @Test - public void makeSureCursorsGetClosedIterateThroughStream() throws Exception { - val stream = eventRepository.load(); - assertNotNull(stream); - val aList = stream.collect(Collectors.toList()); - assertTrue(!aList.isEmpty()); - assertEquals(currentCount, getOpenCursorCount()); - - } - - private CasEvent prepareCasEvent(final AbstractCasEvent event) { - val dto = new CasEvent(); - dto.setType(event.getClass().getCanonicalName()); - dto.putTimestamp(event.getTimestamp()); - val dt = DateTimeUtils.zonedDateTimeOf(Instant.ofEpochMilli(event.getTimestamp())); - dto.setCreationTime(dt.toString()); - return dto; - } - - public long getOpenCursorCount() { - var cmd = new Document("serverStatus", 1); - cmd.append("metrics", true); - cmd.append("cursor", true); - var result = mongoTemplate.executeCommand(cmd); - var open = (Document) result.get("metrics", Document.class).get("cursor", Document.class).get("open", Document.class); - return open.getLong("total"); - } - - } From e1a41de018888e20b80a01f3c206c90903ddacf5 Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 09:55:12 -0500 Subject: [PATCH 035/266] fix: Add try-with-resources on check to see if there are events. This prevents resource leaks with the autoclosable iterator not closing (because findAny() isn't a method that causes the stream to close). In general, its best practice to explictly close streams that are IO bound. It may be better to update the CasMongDBTemplate to fetch the stream, collect it to a list, then stream the list within a try-with-resources clause. I do not know the implications of that. --- .../calcs/BaseAuthenticationRequestRiskCalculator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java b/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java index 2b2e2ac4092f..d3e2ff021790 100644 --- a/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java +++ b/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java @@ -53,9 +53,10 @@ public Stream get() { return getCasTicketGrantingTicketCreatedEventsFor(principal.getId()); } }; - - if (events.get().findAny().isEmpty()) { - return new AuthenticationRiskScore(HIGHEST_RISK_SCORE); + try (val eventStream = events.get()) { + if (eventStream.findAny().isEmpty()) { + return new AuthenticationRiskScore(HIGHEST_RISK_SCORE); + } } val score = new AuthenticationRiskScore(calculateScore(request, authentication, service, events)); LOGGER.debug("Calculated authentication risk score by [{}] is [{}]", getClass().getSimpleName(), score); From 53a7f8fbc8fad118a3848be2cd5e8cc7969f2471 Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 11:58:23 -0500 Subject: [PATCH 036/266] test: Add failing test. Added a test that is supposed to verify the 'event' stream gets closed Mocked out a Stream, by implementing a closable iterator interface to simulate what a data store might do. --- ...henticationRequestRiskCalculatorTests.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java b/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java index 594459258c9a..01813def9e74 100644 --- a/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java +++ b/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java @@ -2,12 +2,21 @@ import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.services.RegisteredServiceTestUtils; +import org.apereo.cas.support.events.dao.CasEvent; import lombok.val; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import org.springframework.data.util.CloseableIterator; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.context.TestPropertySource; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import static org.junit.jupiter.api.Assertions.*; @@ -37,4 +46,62 @@ public void verifyTestWhenAuthnEventsFoundForUser() { val score = authenticationRiskEvaluator.eval(authentication, service, request); assertTrue(score.isLowestRisk()); } + + @Test + public void verifyClosableStreamGetsClosed(){ + val list = new ArrayList(); + val event = new CasEvent(); + val closeCalls = new ArrayList(); + event.setCreationTime("now"); + event.setId(System.currentTimeMillis()); + event.setType("someType"); + list.add(event); + list.add(event); + list.add(event); + val events = new Supplier>() { + @Override + public Stream get() { + val iterator = getCloseableIterator(list, closeCalls); + return StreamSupport.stream(iterator.spliterator(), false); + } + }; + val newList = events.get().collect(Collectors.toList()); + assertTrue(!newList.isEmpty()); + assertTrue(!closeCalls.isEmpty()); + closeCalls.clear(); + val calculator = new DateTimeAuthenticationRequestRiskCalculator(casEventRepository, casProperties); + assertTrue(calculator.hasEvents(events)); + assertTrue(!closeCalls.isEmpty()); + + } + + private static CloseableIterator getCloseableIterator(final List list, final List closeCalls) { + return new CloseableIterator(){ + private Iterator iterator = list.iterator(); + @Override + public void close() { + closeCalls.add(true); + } + + @Override + public boolean hasNext() { + val hasNext = iterator.hasNext(); + if (!hasNext){ + this.close(); + } + return hasNext; + } + + @Override + public CasEvent next() { + val next = iterator.next(); + if (next == null){ + this.close(); + } + return next; + } + }; + } + + } From 77b02b4dcc9927bcc36e463815a5878b78d2506a Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 12:22:32 -0500 Subject: [PATCH 037/266] test: Make test fail again Refactored test to approprateily call iterator.stream() instead of wrapping in a StreamSupport call. --- .../BaseAuthenticationRequestRiskCalculator.java | 11 +++++++---- ...eTimeAuthenticationRequestRiskCalculatorTests.java | 8 +++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java b/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java index d3e2ff021790..842cb5628f2e 100644 --- a/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java +++ b/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java @@ -53,16 +53,19 @@ public Stream get() { return getCasTicketGrantingTicketCreatedEventsFor(principal.getId()); } }; - try (val eventStream = events.get()) { - if (eventStream.findAny().isEmpty()) { - return new AuthenticationRiskScore(HIGHEST_RISK_SCORE); - } + + if (doesNotHaveEvents(events)) { + return new AuthenticationRiskScore(HIGHEST_RISK_SCORE); } val score = new AuthenticationRiskScore(calculateScore(request, authentication, service, events)); LOGGER.debug("Calculated authentication risk score by [{}] is [{}]", getClass().getSimpleName(), score); return score; } + protected boolean doesNotHaveEvents(final Supplier> events) { + return events.get().findAny().isEmpty(); + } + /** * Calculate score authentication risk score. * diff --git a/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java b/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java index 01813def9e74..f9eeeda83acc 100644 --- a/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java +++ b/support/cas-server-support-electrofence/src/test/java/org/apereo/cas/impl/calcs/DateTimeAuthenticationRequestRiskCalculatorTests.java @@ -61,8 +61,7 @@ public void verifyClosableStreamGetsClosed(){ val events = new Supplier>() { @Override public Stream get() { - val iterator = getCloseableIterator(list, closeCalls); - return StreamSupport.stream(iterator.spliterator(), false); + return getCloseableIterator(list, closeCalls).stream(); } }; val newList = events.get().collect(Collectors.toList()); @@ -70,12 +69,12 @@ public Stream get() { assertTrue(!closeCalls.isEmpty()); closeCalls.clear(); val calculator = new DateTimeAuthenticationRequestRiskCalculator(casEventRepository, casProperties); - assertTrue(calculator.hasEvents(events)); + assertTrue(!calculator.doesNotHaveEvents(events)); assertTrue(!closeCalls.isEmpty()); } - private static CloseableIterator getCloseableIterator(final List list, final List closeCalls) { + private CloseableIterator getCloseableIterator(final List list, final List closeCalls) { return new CloseableIterator(){ private Iterator iterator = list.iterator(); @Override @@ -103,5 +102,4 @@ public CasEvent next() { }; } - } From 21c6fb2b597e2ca1a67dcef3ae0dde70d9decd3a Mon Sep 17 00:00:00 2001 From: David Malia Date: Tue, 21 Mar 2023 12:23:16 -0500 Subject: [PATCH 038/266] test: Fix failing test. Put the stream instance in a 'try-with-resources' call --- .../impl/calcs/BaseAuthenticationRequestRiskCalculator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java b/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java index 842cb5628f2e..22a3f6b1fed5 100644 --- a/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java +++ b/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/calcs/BaseAuthenticationRequestRiskCalculator.java @@ -63,7 +63,9 @@ public Stream get() { } protected boolean doesNotHaveEvents(final Supplier> events) { - return events.get().findAny().isEmpty(); + try (val stream = events.get()){ + return stream.findAny().isEmpty(); + } } /** From 55f7b929c47553249492578b7745ed7c2f4586b4 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Tue, 21 Mar 2023 22:13:16 +0400 Subject: [PATCH 039/266] ensure pushed authz uses/merged TGT authn for oidc --- .../authentication/AuthenticationBuilder.java | 15 ++++++++++ .../oidc-par-authzcode-login/script.js | 3 +- .../oidc-par-authzcode-login/script.json | 2 +- .../DefaultAuthenticationBuilder.java | 4 ++- .../DefaultAuthenticationBuilderTests.java | 9 ++++++ .../ext/AccessTokenRequestContext.java | 7 +++-- .../OAuth20AuthorizeEndpointController.java | 2 +- ...uthorizationRequestUriResponseBuilder.java | 29 ++++++++++++------- ...izationRequestUriResponseBuilderTests.java | 16 +++++++--- 9 files changed, 66 insertions(+), 21 deletions(-) diff --git a/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationBuilder.java b/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationBuilder.java index 3120d9c4e02c..25f4a0aca86f 100644 --- a/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationBuilder.java +++ b/api/cas-server-core-api-authentication/src/main/java/org/apereo/cas/authentication/AuthenticationBuilder.java @@ -2,6 +2,8 @@ import org.apereo.cas.authentication.principal.Principal; +import com.google.errorprone.annotations.CanIgnoreReturnValue; + import java.io.Serializable; import java.time.ZonedDateTime; import java.util.List; @@ -180,6 +182,18 @@ public interface AuthenticationBuilder extends Serializable { */ AuthenticationBuilder setAttributes(Map> attributes); + /** + * Merge attribute. + * + * @param toMerge the to merge + * @return the authentication builder + */ + @CanIgnoreReturnValue + default AuthenticationBuilder mergeAttributes(final Map> toMerge) { + toMerge.forEach(this::mergeAttribute); + return this; + } + /** * Merge attribute. * @@ -189,6 +203,7 @@ public interface AuthenticationBuilder extends Serializable { */ AuthenticationBuilder mergeAttribute(String key, Object value); + /** * Merge attribute. * diff --git a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js index 34a7d5c362b0..ab5e1964d716 100644 --- a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js +++ b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.js @@ -32,8 +32,7 @@ const assert = require('assert'); page.setRequestInterception(false); - const url = "https://localhost:8443/cas/oidc/oidcAuthorize?response_type=code" - + "&client_id=client&request_uri=" + requestUri; + const url = `https://localhost:8443/cas/oidc/oidcAuthorize?response_type=code&client_id=client&request_uri=${requestUri}`; await cas.goto(page, url); await page.waitForTimeout(3000); diff --git a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json index ae565622a711..2b2222f74181 100644 --- a/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json +++ b/ci/tests/puppeteer/scenarios/oidc-par-authzcode-login/script.json @@ -18,7 +18,7 @@ "--cas.authn.oidc.discovery.claims=sub,name,cn,given-name,given:name,family_name", "--cas.authn.oidc.core.user-defined-scopes.MyCustomScope=cn,given:name,name,family_name", - "--cas.authn.oidc.jwks.file-system.jwks-file=file:${#systemProperties['java.io.tmpdir']}/keystore.jwks", + "--cas.authn.oidc.jwks.file-system.jwks-file=file:${#systemProperties['java.io.tmpdir']}/parkeystore.jwks", "--cas.authn.oidc.core.claims-map.cn=common-name", "--cas.authn.oidc.core.claims-map.name=identity-name", diff --git a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java index d79cfb094f1d..a7add853039b 100644 --- a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java +++ b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java @@ -180,7 +180,9 @@ public AuthenticationBuilder setWarnings(final List warning) @Override @CanIgnoreReturnValue public AuthenticationBuilder addAttribute(final String key, final List value) { - this.attributes.put(key, value); + if (value != null && !value.isEmpty()) { + this.attributes.put(key, value); + } return this; } diff --git a/core/cas-server-core-authentication-api/src/test/java/org/apereo/cas/authentication/DefaultAuthenticationBuilderTests.java b/core/cas-server-core-authentication-api/src/test/java/org/apereo/cas/authentication/DefaultAuthenticationBuilderTests.java index 165c71e6d8c8..afebedc17dc5 100644 --- a/core/cas-server-core-authentication-api/src/test/java/org/apereo/cas/authentication/DefaultAuthenticationBuilderTests.java +++ b/core/cas-server-core-authentication-api/src/test/java/org/apereo/cas/authentication/DefaultAuthenticationBuilderTests.java @@ -120,4 +120,13 @@ public void verifyUpdateOperation() { assertTrue(authn.getAttributes().containsKey("authn2")); assertTrue(authn.containsAttribute("authn2")); } + + @Test + public void verifyMergeAttributes() { + val authn = DefaultAuthenticationBuilder.newInstance(CoreAuthenticationTestUtils.getAuthentication(Map.of("cn", List.of("cn1")))) + .mergeAttributes(Map.of("cn", List.of("cn2"))) + .build(); + assertTrue(authn.getAttributes().containsKey("cn")); + assertEquals(List.of("cn1", "cn2"), authn.getAttributes().get("cn")); + } } diff --git a/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenRequestContext.java b/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenRequestContext.java index 09ad35d32e2c..612c08149236 100644 --- a/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenRequestContext.java +++ b/support/cas-server-support-oauth-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenRequestContext.java @@ -11,10 +11,12 @@ import org.apereo.cas.ticket.code.OAuth20Code; import org.apereo.cas.ticket.refreshtoken.OAuth20RefreshToken; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import lombok.With; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; import net.minidev.json.annotate.JsonIgnore; @@ -38,6 +40,8 @@ @Getter @SuperBuilder @Jacksonized +@With +@AllArgsConstructor public class AccessTokenRequestContext implements Serializable { @Serial @@ -56,8 +60,7 @@ public class AccessTokenRequestContext implements Serializable { private final OAuthRegisteredService registeredService; - @Setter - private TicketGrantingTicket ticketGrantingTicket; + private final TicketGrantingTicket ticketGrantingTicket; @Builder.Default private final OAuth20GrantTypes grantType = OAuth20GrantTypes.NONE; diff --git a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/endpoints/OAuth20AuthorizeEndpointController.java b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/endpoints/OAuth20AuthorizeEndpointController.java index 2187f6993080..5be499dff95f 100644 --- a/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/endpoints/OAuth20AuthorizeEndpointController.java +++ b/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/endpoints/OAuth20AuthorizeEndpointController.java @@ -247,7 +247,7 @@ protected ModelAndView buildAuthorizationForRequest( .stream() .filter(BeanSupplier::isNotProxy) .sorted(OrderComparator.INSTANCE) - .filter(b -> b.supports(authzRequest)) + .filter(bldr -> bldr.supports(authzRequest)) .findFirst() .map(Unchecked.function(builder -> { if (authzRequest.isSingleSignOnSessionRequired() && payload.getTicketGrantingTicket() == null) { diff --git a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/OidcPushedAuthorizationRequestUriResponseBuilder.java b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/OidcPushedAuthorizationRequestUriResponseBuilder.java index 52bcc7fde51f..88d918f946a9 100644 --- a/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/OidcPushedAuthorizationRequestUriResponseBuilder.java +++ b/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/OidcPushedAuthorizationRequestUriResponseBuilder.java @@ -4,6 +4,7 @@ import org.apereo.cas.audit.AuditResourceResolvers; import org.apereo.cas.audit.AuditableActions; import org.apereo.cas.authentication.Authentication; +import org.apereo.cas.authentication.DefaultAuthenticationBuilder; import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.oidc.OidcConfigurationContext; import org.apereo.cas.oidc.OidcConstants; @@ -71,23 +72,31 @@ public Optional return Optional.empty(); } - val builder = super.toAuthorizationRequest(context, authentication, service, registeredService).get(); + val authzRequestBuilder = super.toAuthorizationRequest(context, authentication, service, registeredService).get(); return requestUri .map(Unchecked.function(uri -> { val factory = (OidcPushedAuthorizationRequestFactory) configurationContext.getTicketFactory().get(OidcPushedAuthorizationRequest.class); - val request = configurationContext.getTicketRegistry().getTicket(uri, OidcPushedAuthorizationRequest.class); - val tokenRequest = factory.toAccessTokenRequest(request); - request.update(); - FunctionUtils.doIf(request.isExpired(), Unchecked.consumer(r -> configurationContext.getTicketRegistry().deleteTicket(request)), - Unchecked.consumer(r -> configurationContext.getTicketRegistry().updateTicket(request))).accept(request); + val pushAuthzTicket = configurationContext.getTicketRegistry().getTicket(uri, OidcPushedAuthorizationRequest.class); + FunctionUtils.doIf(pushAuthzTicket.isExpired(), Unchecked.consumer(r -> configurationContext.getTicketRegistry().deleteTicket(pushAuthzTicket)), + Unchecked.consumer(r -> configurationContext.getTicketRegistry().updateTicket(pushAuthzTicket))).accept(pushAuthzTicket); val tgt = configurationContext.fetchTicketGrantingTicketFrom((JEEContext) context); - tokenRequest.setTicketGrantingTicket(tgt); - return Optional.of(builder.accessTokenRequest(tokenRequest) + + val pushAuthzAuthentication = DefaultAuthenticationBuilder.newInstance(tgt.getAuthentication()) + .mergeAttributes(pushAuthzTicket.getAuthentication().getAttributes()) + .build(); + val tokenRequest = factory.toAccessTokenRequest(pushAuthzTicket) + .withTicketGrantingTicket(tgt) + .withAuthentication(pushAuthzAuthentication); + pushAuthzTicket.update(); + configurationContext.getTicketRegistry().updateTicket(pushAuthzTicket); + + val value = authzRequestBuilder.accessTokenRequest(tokenRequest) .responseType(tokenRequest.getResponseType().getType()) .clientId(tokenRequest.getClientId()) - .grantType(tokenRequest.getGrantType().getType())); + .grantType(tokenRequest.getGrantType().getType()); + return Optional.of(value); })) - .orElseGet(() -> Optional.of(builder.singleSignOnSessionRequired(!context.getRequestURL().endsWith(OidcConstants.PUSHED_AUTHORIZE_URL)))); + .orElseGet(() -> Optional.of(authzRequestBuilder.singleSignOnSessionRequired(!context.getRequestURL().endsWith(OidcConstants.PUSHED_AUTHORIZE_URL)))); } @Override diff --git a/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/ticket/OidcPushedAuthorizationRequestUriResponseBuilderTests.java b/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/ticket/OidcPushedAuthorizationRequestUriResponseBuilderTests.java index ac38654f41a2..4eb2a50d441b 100644 --- a/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/ticket/OidcPushedAuthorizationRequestUriResponseBuilderTests.java +++ b/support/cas-server-support-oidc/src/test/java/org/apereo/cas/oidc/ticket/OidcPushedAuthorizationRequestUriResponseBuilderTests.java @@ -22,6 +22,9 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.TestPropertySource; +import java.util.List; +import java.util.Map; + import static org.junit.jupiter.api.Assertions.*; /** @@ -52,7 +55,8 @@ public void verifyOperation() throws Exception { val holder = AccessTokenRequestContext.builder() .clientId(registeredService.getClientId()) .service(RegisteredServiceTestUtils.getService()) - .authentication(RegisteredServiceTestUtils.getAuthentication()) + .authentication(RegisteredServiceTestUtils.getAuthentication("casuser", + Map.of("customAttribute", List.of("CASUSER-ORIGINAL")))) .registeredService(registeredService) .grantType(OAuth20GrantTypes.AUTHORIZATION_CODE) .responseType(OAuth20ResponseTypes.CODE) @@ -85,11 +89,13 @@ public void verifyOperation() throws Exception { request.addParameter(OidcConstants.REQUEST_URI, uri); - val tgt = new MockTicketGrantingTicket("casuser"); + val authn = RegisteredServiceTestUtils.getAuthentication("casuser", + Map.of("customAttribute", List.of("CASUSER-TGT"))); + val tgt = new MockTicketGrantingTicket(authn); ticketRegistry.addTicket(tgt); - val c = ticketGrantingTicketCookieGenerator.addCookie(request, response, tgt.getId()); - request.setCookies(c); + val cookie = ticketGrantingTicketCookieGenerator.addCookie(request, response, tgt.getId()); + request.setCookies(cookie); context = new JEEContext(request, response); authzRequest = oidcPushedAuthorizationRequestResponseBuilder.toAuthorizationRequest(context, @@ -101,6 +107,8 @@ public void verifyOperation() throws Exception { assertNotNull(accessTokenRequest.getResponseType()); assertNotNull(accessTokenRequest.getGrantType()); assertNotNull(accessTokenRequest.getTicketGrantingTicket()); + val customAttribute = accessTokenRequest.getAuthentication().getAttributes().get("customAttribute"); + assertEquals(List.of("CASUSER-TGT", "CASUSER-ORIGINAL"), customAttribute); assertThrows(InvalidTicketException.class, () -> ticketRegistry.getTicket(uri, OidcPushedAuthorizationRequest.class)); } } From 7aaa39ee48816a27793de1903753a1275d40b9c5 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 22 Mar 2023 10:59:56 +0400 Subject: [PATCH 040/266] update dependencies --- .../release_notes/RC6.md | 5 +++ gradle.properties | 42 +++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index 7188e8617fe5..f80a607b7573 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -67,3 +67,8 @@ Furthermore, sensible defaults would be used if grant types or response types ar - jQuery - Amazon SDK - Spring Boot +- Azure CosmosDb +- Swagger +- Spring BootAdmin +- Slf4j +- PostgreSQL diff --git a/gradle.properties b/gradle.properties index 71a2d9e9fa88..44aaa473ab52 100644 --- a/gradle.properties +++ b/gradle.properties @@ -43,7 +43,7 @@ classgraphVersion=4.8.157 guavaVersion=30.1.1-jre semverVersion=3.1.0 reflectionUtilVersion=2.14.0 -oshiVersion=6.4.0 +oshiVersion=6.4.1 javaParserVersion=3.25.1 snakeYamlVersion=2.0 ############################### @@ -57,7 +57,7 @@ awaitilityVersion=4.2.0 ##################################################### # Gradle Plugins & Build Utilities ###################################################### -checkstyleVersion=10.8.1 +checkstyleVersion=10.9.2 gradleRetryVersion=1.5.2 gradleGitVersion=2.4.1 gradleLombokVersion=5.0.0 @@ -83,12 +83,12 @@ jaxbImplVersion=4.0.2 ############################### # Swagger versions ############################### -swaggerVersion=2.2.8 +swaggerVersion=2.2.9 springDocVersion=2.0.4 ############################### # Logging versions ############################### -slf4jVersion=2.0.6 +slf4jVersion=2.0.7 disruptorVersion=3.4.4 inspektrVersion=2.0.1 sentryRavenVersion=8.0.3 @@ -101,12 +101,12 @@ fluentdLog4jVersion=1.0.0 # Spring versions ############################### springBootVersion=3.0.4 -springVersion=6.0.6 -springBootAdminVersion=3.0.1 +springVersion=6.0.7 +springBootAdminVersion=3.0.2 ############################### # Spring Retry versions ############################### -springRetryVersion=2.0.0 +springRetryVersion=2.0.1 ############################### # Spring Integration versions ############################### @@ -118,10 +118,10 @@ springWebflowVersion=2.6.0 ############################### # Spring Data versions ############################### -springDataCommonsVersion=3.0.3 -springDataMongoDbVersion=4.0.3 -springDataRedisVersion=3.0.3 -springDataCassandraVersion=4.0.3 +springDataCommonsVersion=3.0.4 +springDataMongoDbVersion=4.0.4 +springDataRedisVersion=3.0.4 +springDataCassandraVersion=4.0.4 ############################### # Spring Security versions ############################### @@ -144,7 +144,7 @@ springCloudKubernetesConfig=3.0.1 # Spring WS & Kafka versions ############################### springWsVersion=4.0.2 -springKafkaVersion=3.0.4 +springKafkaVersion=3.0.5 kafkaVersion=3.4.0 wss4jVersion=4.0.0 wsdl4jVersion=1.6.3 @@ -180,7 +180,7 @@ hsqlVersion=2.7.1 hikariVersion=5.0.1 h2Version=1.4.197 mysqlVersion=8.0.32 -postgresqlVersion=42.5.4 +postgresqlVersion=42.6.0 yugabytedbVersion=42.3.4 mariaDbVersion=3.1.2 jtdsVersion=1.3.1 @@ -256,8 +256,8 @@ dropwizardVersion=4.2.17 ############################### # Spring Session versions ############################### -springSessionVersion=3.0.0 -springSessionMongoVersion=3.0.0 +springSessionVersion=3.0.1 +springSessionMongoVersion=3.0.1 ############################### # Messaging & RabbitMQ versions ############################### @@ -265,12 +265,12 @@ springRabbitVersion=3.0.2 ############################### # Amazon SDK versions ############################### -amazonSdkVersion=2.20.21 +amazonSdkVersion=2.20.29 ############################### # Azure CosmosDb versions ############################### -cosmosdbVersion=4.41.0 -springDataCosmosDbVersion=3.32.0 +cosmosdbVersion=4.42.0 +springDataCosmosDbVersion=3.33.0 ############################### # Azure versions ############################### @@ -282,7 +282,7 @@ azureadVersion=1.13.5 jsonVersion=20220924 hjsonVersion=3.0.0 jsoupVersion=1.15.4 -jsonSmartVersion=2.4.9 +jsonSmartVersion=2.4.10 jsonassertVersion=1.5.1 jacksonVersion=2.14.2 jacksonDataBindVersion=2.14.2 @@ -412,7 +412,7 @@ gsonVersion=2.10.1 # Google SDK / Spring Cloud ############################### googleCloudSdkVersion=4.1.2 -googleCloudMonitorVersion=3.13.0 +googleCloudMonitorVersion=3.14.0 ############################### # CouchDb Versions ############################### @@ -429,7 +429,7 @@ bootstrapVersion=5.2.3 fontAwesomeVersion=6.3.0 datatablesVersion=1.13.2 bootstrapSelectVersion=1.13.18 -mdiFontVersion=7.0.96 +mdiFontVersion=7.2.96 materialVersion=14.0.0 normalizeVersion=8.0.1 es5ShimVersion=4.5.9 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bdc9a83b1e65..7161bf2bc13e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-rc-1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 8f1135873e28350bcc1f5ff62cce08ad99db3027 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 22 Mar 2023 11:06:38 +0400 Subject: [PATCH 041/266] switch ci to jdk 20 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be0a2539a561..9a0d1d82983f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ env: GH_PACKAGE_REGISTRY_USER: ${{ secrets.GH_PACKAGE_REGISTRY_USER }} GH_PACKAGE_REGISTRY_TOKEN: ${{ secrets.GH_PACKAGE_REGISTRY_TOKEN }} JDK_CURRENT: 17 - JDK_LATEST: 20-ea + JDK_LATEST: 20 ########################################################################## From 10436bf8c5ee49b76835bbc8fb783f22af113f62 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Wed, 22 Mar 2023 20:42:16 +0400 Subject: [PATCH 042/266] remove couchbase/couchdb modules --- .../core/audit/AuditCouchDbProperties.java | 29 -- .../core/audit/AuditCouchbaseProperties.java | 32 --- .../model/core/audit/AuditProperties.java | 12 - .../AuthenticationProperties.java | 14 - .../PrincipalAttributesProperties.java | 7 - .../core/events/CouchDbEventsProperties.java | 35 --- .../model/core/events/EventsProperties.java | 6 - .../services/ServiceRegistryProperties.java | 14 - .../registry/TicketRegistryProperties.java | 7 - .../aup/AcceptableUsagePolicyProperties.java | 12 - ...ouchDbAcceptableUsagePolicyProperties.java | 34 --- ...chbaseAcceptableUsagePolicyProperties.java | 29 -- .../support/consent/ConsentProperties.java | 6 - .../consent/CouchDbConsentProperties.java | 31 --- .../couchbase/BaseCouchbaseProperties.java | 127 --------- .../CouchbaseAuthenticationProperties.java | 66 ----- ...ouchbasePrincipalAttributesProperties.java | 46 --- .../CouchbaseServiceRegistryProperties.java | 27 -- .../BaseAsynchronousCouchDbProperties.java | 30 -- .../couchdb/BaseCouchDbProperties.java | 121 -------- .../CouchDbAuthenticationProperties.java | 75 ----- .../CouchDbServiceRegistryProperties.java | 33 --- .../CouchDbTicketRegistryProperties.java | 40 --- ...gleAuthenticatorMultifactorProperties.java | 34 --- ...gleAuthenticatorMultifactorProperties.java | 6 - ...DbTrustedDevicesMultifactorProperties.java | 34 --- .../TrustedDevicesMultifactorProperties.java | 6 - ...DbMultifactorAuthenticationProperties.java | 34 --- ...2FMultifactorAuthenticationProperties.java | 8 +- .../YubiKeyCouchDbMultifactorProperties.java | 31 --- ...eyMultifactorAuthenticationProperties.java | 6 - .../CouchDbSamlMetadataProperties.java | 51 ---- .../metadata/SamlIdPMetadataProperties.java | 6 - .../SurrogateAuthenticationProperties.java | 6 - ...rogateCouchDbAuthenticationProperties.java | 47 ---- ci/tests/couchbase/run-couchbase-server.sh | 128 --------- ci/tests/couchdb/run-couchdb-server.sh | 38 --- .../DefaultAuthenticationBuilder.java | 4 +- .../audits/Audits-CouchDb.md | 19 -- .../audits/Audits-Couchbase.md | 18 -- .../cas-server-documentation/audits/Audits.md | 2 - ...nfiguring-Authentication-Events-CouchDb.md | 19 -- .../Configuring-Authentication-Events.md | 1 - ...uring-Authentication-Throttling-CouchDb.md | 25 -- .../Configuring-Authentication-Throttling.md | 1 - .../authentication/CouchDb-Authentication.md | 22 -- .../Couchbase-Authentication.md | 32 --- ...urrogate-Authentication-Storage-CouchDb.md | 19 -- .../Surrogate-Authentication.md | 1 - ...nfiguring-SAML2-DynamicMetadata-CouchDb.md | 74 ----- .../Configuring-SAML2-DynamicMetadata.md | 1 - .../SAML2-ServiceProvider-Metadata.md | 1 - .../Ticket-Registry-Replication-Encryption.md | 1 - ...tribute-Release-Consent-Storage-CouchDb.md | 21 -- .../integration/Attribute-Release-Consent.md | 1 - .../Attribute-Resolution-Couchbase.md | 20 -- .../integration/Attribute-Resolution.md | 1 - .../Configuring-SAML-SP-Integrations.md | 4 +- .../logging/Logging.md | 2 +- .../mfa/FIDO-U2F-Authentication-CouchDb.md | 19 -- .../mfa/FIDO-U2F-Authentication.md | 1 - ...tor-Authentication-Registration-CouchDb.md | 20 -- .../mfa/GoogleAuthenticator-Authentication.md | 1 - ...edDevice-Authentication-Storage-CouchDb.md | 25 -- ...ultifactor-TrustedDevice-Authentication.md | 1 - ...Key-Authentication-Registration-CouchDb.md | 28 -- .../mfa/YubiKey-Authentication.md | 1 - .../release_notes/RC6.md | 6 + .../services/CouchDb-Service-Management.md | 43 --- .../services/Couchbase-Service-Management.md | 51 ---- .../services/Service-Management.md | 2 - docs/cas-server-documentation/sidebar.md | 17 -- .../Configuring-Ticketing-Components.md | 1 - .../ticketing/CouchDb-Ticket-Registry.md | 48 ---- .../Webflow-Customization-AUP-CouchDb.md | 23 -- .../Webflow-Customization-AUP-Couchbase.md | 22 -- .../webflow/Webflow-Customization-AUP.md | 2 - gradle.properties | 8 - gradle/dependencies.gradle | 26 +- gradle/maven.gradle | 6 - gradle/overrides.gradle | 3 - gradle/tests.gradle | 2 - settings.gradle | 20 -- .../build.gradle | 37 --- .../cas/audit/CouchbaseAuditTrailManager.java | 83 ------ ...CasSupportCouchbaseAuditConfiguration.java | 63 ----- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../CouchbaseAuditTrailManagerTests.java | 52 ---- .../src/test/resources/log4j2-test.xml | 15 - .../build.gradle | 32 --- .../cas/audit/CouchDbAuditTrailManager.java | 44 --- .../CasSupportCouchDbAuditConfiguration.java | 69 ----- .../AuditActionContextCouchDbRepository.java | 69 ----- .../audit/CouchDbAuditActionContext.java | 55 ---- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../cas/couchdb/audit/by_throttle_params.js | 6 - .../cas/couchdb/audit/by_when_params.js | 6 - .../audit/CouchDbAuditTrailManagerTests.java | 69 ----- .../src/test/resources/log4j2-test.xml | 15 - .../build.gradle | 49 ---- ...chbaseAcceptableUsagePolicyRepository.java | 57 ---- ...ableUsagePolicyCouchbaseConfiguration.java | 58 ---- ...ot.autoconfigure.AutoConfiguration.imports | 1 - ...eAcceptableUsagePolicyRepositoryTests.java | 56 ---- .../src/test/resources/log4j2-test.xml | 16 -- .../build.gradle | 47 ---- ...ouchDbAcceptableUsagePolicyRepository.java | 92 ------ ...ptableUsagePolicyCouchDbConfiguration.java | 88 ------ ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../java/org/apereo/cas/AllTestsSuite.java | 17 -- ...bAcceptableUsagePolicyRepositoryTests.java | 102 ------- .../src/test/resources/log4j2-test.xml | 16 -- .../build.gradle | 45 --- .../CasConsentCouchDbConfiguration.java | 65 ----- .../cas/consent/CouchDbConsentRepository.java | 94 ------- .../ConsentDecisionCouchDbRepository.java | 107 ------- .../consent/CouchDbConsentDecision.java | 97 ------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../java/org/apereo/cas/AllTestsSuite.java | 21 -- .../consent/CouchDbConsentDecisionTests.java | 57 ---- .../CouchDbConsentRepositoryTests.java | 80 ------ .../src/test/resources/log4j2-test.xml | 14 - .../build.gradle | 45 --- .../CouchbaseAuthenticationHandler.java | 73 ----- .../CouchbaseAuthenticationConfiguration.java | 97 ------- ...CouchbasePersonDirectoryConfiguration.java | 71 ----- .../support/CouchbasePersonAttributeDao.java | 99 ------- ...ot.autoconfigure.AutoConfiguration.imports | 2 - .../apereo/cas/AbstractCouchbaseTests.java | 74 ----- .../java/org/apereo/cas/AllTestsSuite.java | 23 -- .../CouchbaseAuthenticationHandlerTests.java | 99 ------- .../CouchbasePersonAttributeDaoTests.java | 70 ----- .../config/CouchbaseConfigurationTests.java | 51 ---- .../test/resources/couchbase-authn.properties | 0 .../src/test/resources/log4j2-test.xml | 15 - .../build.gradle | 8 - .../core/CouchbaseClientFactory.java | 255 ----------------- .../core/DefaultCouchbaseClientFactory.java | 263 ------------------ .../core/CouchbaseClientFactoryTests.java | 56 ---- .../build.gradle | 36 --- ...CouchbaseServiceRegistryConfiguration.java | 71 ----- ...ouchbaseRegisteredServiceDeletedEvent.java | 22 -- .../CouchbaseRegisteredServiceSavedEvent.java | 22 -- .../services/CouchbaseServiceRegistry.java | 133 --------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../CouchbaseServiceRegistryTests.java | 106 ------- .../src/test/resources/log4j2-test.xml | 15 - .../src/test/resources/services/.donotdelete | 0 .../build.gradle | 38 --- .../CouchDbAuthenticationHandler.java | 22 -- .../CouchDbAuthenticationConfiguration.java | 117 -------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../CouchDbAuthenticationHandlerTests.java | 144 ---------- .../build.gradle | 7 - .../config/CasCouchDbCoreConfiguration.java | 39 --- .../couchdb/core/CasObjectMapperFactory.java | 25 -- .../couchdb/core/CouchDbConnectorFactory.java | 51 ---- .../couchdb/core/CouchDbProfileDocument.java | 83 ------ .../core/DefaultCouchDbConnectorFactory.java | 108 ------- .../core/DefaultProfileCouchDbRepository.java | 37 --- .../core/ProfileCouchDbRepository.java | 34 --- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../src/test/resources/log4j2-test.xml | 14 - .../build.gradle | 33 --- .../CouchDbServiceRegistryConfiguration.java | 96 ------- .../RegisteredServiceCouchDbRepository.java | 96 ------- .../services/RegisteredServiceDocument.java | 30 -- .../cas/services/CouchDbServiceRegistry.java | 109 -------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../RegisteredServiceDocument_delete.js | 8 - .../java/org/apereo/cas/AllTestsSuite.java | 21 -- ...gisteredServiceCouchDbRepositoryTests.java | 57 ---- .../services/CouchDbServiceRegistryTests.java | 64 ----- .../src/test/resources/log4j2-test.xml | 22 -- .../build.gradle | 40 --- .../CouchDbTicketRegistryConfiguration.java | 84 ------ .../cas/couchdb/tickets/TicketDocument.java | 36 --- .../cas/couchdb/tickets/TicketRepository.java | 49 ---- .../registry/CouchDbTicketRegistry.java | 141 ---------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../registry/CouchDbTicketRegistryTests.java | 84 ------ .../build.gradle | 27 -- .../config/CouchDbEventsConfiguration.java | 78 ------ .../cas/couchdb/events/CouchDbCasEvent.java | 68 ----- .../events/EventCouchDbRepository.java | 130 --------- .../events/CouchDbCasEventRepository.java | 100 ------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../CouchDbCasEventRepositoryTests.java | 64 ----- .../src/test/resources/log4j2-test.xml | 15 - .../build.gradle | 47 ---- ...ogleAuthenticatorCouchDbConfiguration.java | 106 ------- .../CouchDbGoogleAuthenticatorAccount.java | 64 ----- ...AuthenticatorAccountCouchDbRepository.java | 113 -------- .../CouchDbGoogleAuthenticatorToken.java | 57 ---- ...leAuthenticatorTokenCouchDbRepository.java | 128 --------- ...uthenticatorTokenCredentialRepository.java | 106 ------- ...leAuthenticatorCouchDbTokenRepository.java | 81 ------ ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../CouchDbOneTimeTokenAccount_delete.js | 8 - .../gauth/token/CouchDbOneTimeToken_delete.js | 8 - .../java/org/apereo/cas/AllTestsSuite.java | 22 -- ...ticatorTokenCredentialRepositoryTests.java | 71 ----- ...henticatorCouchDbTokenRepositoryTests.java | 120 -------- .../src/test/resources/log4j2-test.xml | 15 - .../rest/resources/ServiceTicketResource.java | 3 +- .../TicketGrantingTicketResource.java | 2 +- .../rest/resources/TicketStatusResource.java | 2 +- .../resources/UserAuthenticationResource.java | 2 +- .../build.gradle | 54 ---- .../CouchDbSamlIdPFactoryConfiguration.java | 40 --- .../CouchDbSamlIdPMetadataConfiguration.java | 161 ----------- ...egisteredServiceMetadataConfiguration.java | 70 ----- .../saml/CouchDbSamlIdPMetadataDocument.java | 71 ----- .../saml/CouchDbSamlMetadataDocument.java | 66 ----- ...faultSamlIdPMetadataCouchDbRepository.java | 49 ---- .../SamlIdPMetadataCouchDbRepository.java | 40 --- ...SamlMetadataDocumentCouchDbRepository.java | 32 --- .../CouchDbSamlIdPMetadataCipherExecutor.java | 36 --- .../CouchDbSamlIdPMetadataGenerator.java | 57 ---- .../CouchDbSamlIdPMetadataLocator.java | 43 --- ...SamlRegisteredServiceMetadataResolver.java | 77 ----- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../java/org/apereo/cas/AllTestsSuite.java | 26 -- .../CouchDbSamlIdPMetadataDocumentTests.java | 45 --- .../CouchDbSamlMetadataDocumentTests.java | 43 --- .../CouchDbSamlIdPMetadataGeneratorTests.java | 108 ------- ...egisteredServiceMetadataResolverTests.java | 105 ------- .../src/test/resources/log4j2-test.xml | 15 - .../src/test/resources/samlsp-metadata.xml | 74 ----- .../build.gradle | 47 ---- ...SurrogateCouchDbAuthenticationService.java | 37 --- ...teCouchDbProfileAuthenticationService.java | 80 ------ ...hDbAuthenticationServiceConfiguration.java | 109 -------- .../CouchDbSurrogateAuthorization.java | 41 --- ...rrogateAuthorizationCouchDbRepository.java | 46 --- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../java/org/apereo/cas/AllTestsSuite.java | 22 -- .../SurrogateCouchDbAuthenticationTests.java | 64 ----- ...chDbProfileAuthenticationServiceTests.java | 77 ----- .../src/test/resources/log4j2-test.xml | 16 -- .../build.gradle | 46 --- .../CasCouchDbThrottlingConfiguration.java | 40 --- ...edSubmissionHandlerInterceptorAdapter.java | 54 ---- ...ot.autoconfigure.AutoConfiguration.imports | 1 - ...missionHandlerInterceptorAdapterTests.java | 70 ----- .../build.gradle | 35 --- ...actorAuthenticationTrustConfiguration.java | 68 ----- ...bMultifactorAuthenticationTrustRecord.java | 82 ------ ...nticationTrustRecordCouchDbRepository.java | 146 ---------- ...MultifactorAuthenticationTrustStorage.java | 90 ------ ...ot.autoconfigure.AutoConfiguration.imports | 1 - ...factorAuthenticationTrustStorageTests.java | 105 ------- .../src/test/resources/log4j2-test.xml | 15 - .../build.gradle | 37 --- .../storage/U2FCouchDbDeviceRepository.java | 112 -------- .../cas/config/U2FCouchDbConfiguration.java | 76 ----- .../u2f/CouchDbU2FDeviceRegistration.java | 51 ---- ...2FDeviceRegistrationCouchDbRepository.java | 72 ----- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../org/apereo/cas/couchdb/u2f/delete.js | 8 - .../U2FCouchDbDeviceRepositoryTests.java | 77 ----- .../src/test/resources/log4j2-test.xml | 16 -- .../build.gradle | 47 ---- .../dao/CouchDbYubiKeyAccountRegistry.java | 88 ------ .../config/CouchDbYubiKeyConfiguration.java | 91 ------ .../yubikey/CouchDbYubiKeyAccount.java | 53 ---- .../YubiKeyAccountCouchDbRepository.java | 59 ---- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../CouchDbYubiKeyAccountRegistryTests.java | 81 ------ .../src/test/resources/log4j2-test.xml | 16 -- .../build.gradle | 2 +- testcas.sh | 8 - .../src/main/resources/log4j2.xml | 1 - 273 files changed, 33 insertions(+), 11940 deletions(-) delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchDbProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchbaseProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/CouchDbEventsProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchDbAcceptableUsagePolicyProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchbaseAcceptableUsagePolicyProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/CouchDbConsentProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/BaseCouchbaseProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbaseAuthenticationProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbasePrincipalAttributesProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/serviceregistry/CouchbaseServiceRegistryProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseAsynchronousCouchDbProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseCouchDbProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/authentication/CouchDbAuthenticationProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/serviceregistry/CouchDbServiceRegistryProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/ticketregistry/CouchDbTicketRegistryProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/CouchDbGoogleAuthenticatorMultifactorProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/CouchDbTrustedDevicesMultifactorProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FCouchDbMultifactorAuthenticationProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyCouchDbMultifactorProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/CouchDbSamlMetadataProperties.java delete mode 100644 api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateCouchDbAuthenticationProperties.java delete mode 100755 ci/tests/couchbase/run-couchbase-server.sh delete mode 100755 ci/tests/couchdb/run-couchdb-server.sh delete mode 100644 docs/cas-server-documentation/audits/Audits-CouchDb.md delete mode 100644 docs/cas-server-documentation/audits/Audits-Couchbase.md delete mode 100644 docs/cas-server-documentation/authentication/Configuring-Authentication-Events-CouchDb.md delete mode 100644 docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling-CouchDb.md delete mode 100644 docs/cas-server-documentation/authentication/CouchDb-Authentication.md delete mode 100644 docs/cas-server-documentation/authentication/Couchbase-Authentication.md delete mode 100644 docs/cas-server-documentation/authentication/Surrogate-Authentication-Storage-CouchDb.md delete mode 100644 docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata-CouchDb.md delete mode 100644 docs/cas-server-documentation/integration/Attribute-Release-Consent-Storage-CouchDb.md delete mode 100644 docs/cas-server-documentation/integration/Attribute-Resolution-Couchbase.md delete mode 100644 docs/cas-server-documentation/mfa/FIDO-U2F-Authentication-CouchDb.md delete mode 100644 docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication-Registration-CouchDb.md delete mode 100644 docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication-Storage-CouchDb.md delete mode 100644 docs/cas-server-documentation/mfa/YubiKey-Authentication-Registration-CouchDb.md delete mode 100644 docs/cas-server-documentation/services/CouchDb-Service-Management.md delete mode 100644 docs/cas-server-documentation/services/Couchbase-Service-Management.md delete mode 100644 docs/cas-server-documentation/ticketing/CouchDb-Ticket-Registry.md delete mode 100644 docs/cas-server-documentation/webflow/Webflow-Customization-AUP-CouchDb.md delete mode 100644 docs/cas-server-documentation/webflow/Webflow-Customization-AUP-Couchbase.md delete mode 100644 support/cas-server-support-audit-couchbase/build.gradle delete mode 100644 support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/audit/CouchbaseAuditTrailManager.java delete mode 100644 support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/config/CasSupportCouchbaseAuditConfiguration.java delete mode 100644 support/cas-server-support-audit-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-audit-couchbase/src/test/java/org/apereo/cas/audit/CouchbaseAuditTrailManagerTests.java delete mode 100644 support/cas-server-support-audit-couchbase/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-audit-couchdb/build.gradle delete mode 100644 support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/audit/CouchDbAuditTrailManager.java delete mode 100644 support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/config/CasSupportCouchDbAuditConfiguration.java delete mode 100644 support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/AuditActionContextCouchDbRepository.java delete mode 100644 support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/CouchDbAuditActionContext.java delete mode 100644 support/cas-server-support-audit-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_throttle_params.js delete mode 100644 support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_when_params.js delete mode 100644 support/cas-server-support-audit-couchdb/src/test/java/org/apereo/cas/audit/CouchDbAuditTrailManagerTests.java delete mode 100644 support/cas-server-support-audit-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-aup-couchbase/build.gradle delete mode 100644 support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepository.java delete mode 100644 support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchbaseConfiguration.java delete mode 100644 support/cas-server-support-aup-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-aup-couchbase/src/test/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepositoryTests.java delete mode 100644 support/cas-server-support-aup-couchbase/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-aup-couchdb/build.gradle delete mode 100644 support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepository.java delete mode 100644 support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchDbConfiguration.java delete mode 100644 support/cas-server-support-aup-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepositoryTests.java delete mode 100644 support/cas-server-support-aup-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-consent-couchdb/build.gradle delete mode 100644 support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/config/CasConsentCouchDbConfiguration.java delete mode 100644 support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/consent/CouchDbConsentRepository.java delete mode 100644 support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/ConsentDecisionCouchDbRepository.java delete mode 100644 support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/CouchDbConsentDecision.java delete mode 100644 support/cas-server-support-consent-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentDecisionTests.java delete mode 100644 support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentRepositoryTests.java delete mode 100644 support/cas-server-support-consent-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-couchbase-authentication/build.gradle delete mode 100644 support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandler.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbaseAuthenticationConfiguration.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbasePersonDirectoryConfiguration.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/persondir/support/CouchbasePersonAttributeDao.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AbstractCouchbaseTests.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandlerTests.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbasePersonAttributeDaoTests.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/config/CouchbaseConfigurationTests.java delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/resources/couchbase-authn.properties delete mode 100644 support/cas-server-support-couchbase-authentication/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-couchbase-core/build.gradle delete mode 100644 support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/CouchbaseClientFactory.java delete mode 100644 support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/DefaultCouchbaseClientFactory.java delete mode 100644 support/cas-server-support-couchbase-core/src/test/java/org/apereo/cas/couchbase/core/CouchbaseClientFactoryTests.java delete mode 100644 support/cas-server-support-couchbase-service-registry/build.gradle delete mode 100644 support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/config/CouchbaseServiceRegistryConfiguration.java delete mode 100644 support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceDeletedEvent.java delete mode 100644 support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceSavedEvent.java delete mode 100644 support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseServiceRegistry.java delete mode 100644 support/cas-server-support-couchbase-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-couchbase-service-registry/src/test/java/org/apereo/cas/services/CouchbaseServiceRegistryTests.java delete mode 100644 support/cas-server-support-couchbase-service-registry/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-couchbase-service-registry/src/test/resources/services/.donotdelete delete mode 100644 support/cas-server-support-couchdb-authentication/build.gradle delete mode 100644 support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/authentication/CouchDbAuthenticationHandler.java delete mode 100644 support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/config/CouchDbAuthenticationConfiguration.java delete mode 100644 support/cas-server-support-couchdb-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-couchdb-authentication/src/test/java/org/apereo/cas/authentication/CouchDbAuthenticationHandlerTests.java delete mode 100644 support/cas-server-support-couchdb-core/build.gradle delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/config/CasCouchDbCoreConfiguration.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CasObjectMapperFactory.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbConnectorFactory.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbProfileDocument.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultCouchDbConnectorFactory.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultProfileCouchDbRepository.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/ProfileCouchDbRepository.java delete mode 100644 support/cas-server-support-couchdb-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-couchdb-core/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-couchdb-service-registry/build.gradle delete mode 100644 support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/config/CouchDbServiceRegistryConfiguration.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepository.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceDocument.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/services/CouchDbServiceRegistry.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-couchdb-service-registry/src/main/resources/org/apereo/cas/couchdb/services/RegisteredServiceDocument_delete.js delete mode 100644 support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepositoryTests.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/services/CouchDbServiceRegistryTests.java delete mode 100644 support/cas-server-support-couchdb-service-registry/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-couchdb-ticket-registry/build.gradle delete mode 100644 support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/config/CouchDbTicketRegistryConfiguration.java delete mode 100644 support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketDocument.java delete mode 100644 support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketRepository.java delete mode 100644 support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistry.java delete mode 100644 support/cas-server-support-couchdb-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-couchdb-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistryTests.java delete mode 100644 support/cas-server-support-events-couchdb/build.gradle delete mode 100644 support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/config/CouchDbEventsConfiguration.java delete mode 100644 support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/CouchDbCasEvent.java delete mode 100644 support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/EventCouchDbRepository.java delete mode 100644 support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/support/events/CouchDbCasEventRepository.java delete mode 100644 support/cas-server-support-events-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-events-couchdb/src/test/java/org/apereo/cas/support/events/couchdb/CouchDbCasEventRepositoryTests.java delete mode 100644 support/cas-server-support-events-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-gauth-couchdb/build.gradle delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/config/GoogleAuthenticatorCouchDbConfiguration.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/CouchDbGoogleAuthenticatorAccount.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/GoogleAuthenticatorAccountCouchDbRepository.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/CouchDbGoogleAuthenticatorToken.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/GoogleAuthenticatorTokenCouchDbRepository.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepository.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepository.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/credential/CouchDbOneTimeTokenAccount_delete.js delete mode 100644 support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/token/CouchDbOneTimeToken_delete.js delete mode 100644 support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepositoryTests.java delete mode 100644 support/cas-server-support-gauth-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/build.gradle delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/config/CouchDbSamlIdPFactoryConfiguration.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/config/CouchDbSamlIdPMetadataConfiguration.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/config/SamlIdPCouchDbRegisteredServiceMetadataConfiguration.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/couchdb/saml/CouchDbSamlIdPMetadataDocument.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/couchdb/saml/CouchDbSamlMetadataDocument.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/couchdb/saml/DefaultSamlIdPMetadataCouchDbRepository.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/couchdb/saml/SamlIdPMetadataCouchDbRepository.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/couchdb/saml/SamlMetadataDocumentCouchDbRepository.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/support/saml/idp/metadata/CouchDbSamlIdPMetadataCipherExecutor.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/support/saml/idp/metadata/CouchDbSamlIdPMetadataGenerator.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/support/saml/idp/metadata/CouchDbSamlIdPMetadataLocator.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/java/org/apereo/cas/support/saml/metadata/resolver/CouchDbSamlRegisteredServiceMetadataResolver.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/java/org/apereo/cas/support/saml/CouchDbSamlIdPMetadataDocumentTests.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/java/org/apereo/cas/support/saml/CouchDbSamlMetadataDocumentTests.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/java/org/apereo/cas/support/saml/idp/metadata/CouchDbSamlIdPMetadataGeneratorTests.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/java/org/apereo/cas/support/saml/metadata/resolver/CouchDbSamlRegisteredServiceMetadataResolverTests.java delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-saml-idp-metadata-couchdb/src/test/resources/samlsp-metadata.xml delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/build.gradle delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/main/java/org/apereo/cas/authentication/surrogate/SurrogateCouchDbAuthenticationService.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/main/java/org/apereo/cas/authentication/surrogate/SurrogateCouchDbProfileAuthenticationService.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/main/java/org/apereo/cas/config/SurrogateCouchDbAuthenticationServiceConfiguration.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/main/java/org/apereo/cas/couchdb/surrogate/CouchDbSurrogateAuthorization.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/main/java/org/apereo/cas/couchdb/surrogate/SurrogateAuthorizationCouchDbRepository.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/test/java/org/apereo/cas/authentication/surrogate/SurrogateCouchDbAuthenticationTests.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/test/java/org/apereo/cas/authentication/surrogate/SurrogateCouchDbProfileAuthenticationServiceTests.java delete mode 100644 support/cas-server-support-surrogate-authentication-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-throttle-couchdb/build.gradle delete mode 100644 support/cas-server-support-throttle-couchdb/src/main/java/org/apereo/cas/config/CasCouchDbThrottlingConfiguration.java delete mode 100644 support/cas-server-support-throttle-couchdb/src/main/java/org/apereo/cas/web/support/CouchDbThrottledSubmissionHandlerInterceptorAdapter.java delete mode 100644 support/cas-server-support-throttle-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-throttle-couchdb/src/test/java/org/apereo/cas/web/support/CouchDbThrottledSubmissionHandlerInterceptorAdapterTests.java delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/build.gradle delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/main/java/org/apereo/cas/config/CouchDbMultifactorAuthenticationTrustConfiguration.java delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/main/java/org/apereo/cas/couchdb/trusted/CouchDbMultifactorAuthenticationTrustRecord.java delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/main/java/org/apereo/cas/couchdb/trusted/MultifactorAuthenticationTrustRecordCouchDbRepository.java delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/main/java/org/apereo/cas/trusted/authentication/storage/CouchDbMultifactorAuthenticationTrustStorage.java delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/test/java/org/apereo/cas/trusted/authentication/storage/CouchDbMultifactorAuthenticationTrustStorageTests.java delete mode 100644 support/cas-server-support-trusted-mfa-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-u2f-couchdb/build.gradle delete mode 100644 support/cas-server-support-u2f-couchdb/src/main/java/org/apereo/cas/adaptors/u2f/storage/U2FCouchDbDeviceRepository.java delete mode 100644 support/cas-server-support-u2f-couchdb/src/main/java/org/apereo/cas/config/U2FCouchDbConfiguration.java delete mode 100644 support/cas-server-support-u2f-couchdb/src/main/java/org/apereo/cas/couchdb/u2f/CouchDbU2FDeviceRegistration.java delete mode 100644 support/cas-server-support-u2f-couchdb/src/main/java/org/apereo/cas/couchdb/u2f/U2FDeviceRegistrationCouchDbRepository.java delete mode 100644 support/cas-server-support-u2f-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-u2f-couchdb/src/main/resources/org/apereo/cas/couchdb/u2f/delete.js delete mode 100644 support/cas-server-support-u2f-couchdb/src/test/java/org/apereo/cas/adaptors/u2f/storage/U2FCouchDbDeviceRepositoryTests.java delete mode 100644 support/cas-server-support-u2f-couchdb/src/test/resources/log4j2-test.xml delete mode 100644 support/cas-server-support-yubikey-couchdb/build.gradle delete mode 100644 support/cas-server-support-yubikey-couchdb/src/main/java/org/apereo/cas/adaptors/yubikey/dao/CouchDbYubiKeyAccountRegistry.java delete mode 100644 support/cas-server-support-yubikey-couchdb/src/main/java/org/apereo/cas/config/CouchDbYubiKeyConfiguration.java delete mode 100644 support/cas-server-support-yubikey-couchdb/src/main/java/org/apereo/cas/couchdb/yubikey/CouchDbYubiKeyAccount.java delete mode 100644 support/cas-server-support-yubikey-couchdb/src/main/java/org/apereo/cas/couchdb/yubikey/YubiKeyAccountCouchDbRepository.java delete mode 100644 support/cas-server-support-yubikey-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 support/cas-server-support-yubikey-couchdb/src/test/java/org/apereo/cas/adaptors/yubikey/dao/CouchDbYubiKeyAccountRegistryTests.java delete mode 100644 support/cas-server-support-yubikey-couchdb/src/test/resources/log4j2-test.xml diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchDbProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchDbProperties.java deleted file mode 100644 index fb6abfa24abd..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchDbProperties.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.apereo.cas.configuration.model.core.audit; - -import org.apereo.cas.configuration.model.support.couchdb.BaseAsynchronousCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link AuditCouchDbProperties}. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@RequiresModule(name = "cas-server-support-audit-couchdb") -@Getter -@Setter -@Accessors(chain = true) -public class AuditCouchDbProperties extends BaseAsynchronousCouchDbProperties { - @Serial - private static final long serialVersionUID = -5607529769937667881L; - - public AuditCouchDbProperties() { - setDbName("audit"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchbaseProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchbaseProperties.java deleted file mode 100644 index d5b997c14b93..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditCouchbaseProperties.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.apereo.cas.configuration.model.core.audit; - -import org.apereo.cas.configuration.model.support.couchbase.BaseCouchbaseProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link AuditCouchbaseProperties}. - * - * @author Misagh Moayyed - * @since 6.0.0 - * @deprecated Since 7.0.0 - */ -@RequiresModule(name = "cas-server-support-audit-couchbase") -@Getter -@Setter -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class AuditCouchbaseProperties extends BaseCouchbaseProperties { - @Serial - private static final long serialVersionUID = 580545095591694L; - - /** - * Whether audit records should be executed asynchronously. - */ - private boolean asynchronous; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditProperties.java index bb349ce96b76..c0ce4204f71f 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/audit/AuditProperties.java @@ -48,12 +48,6 @@ public class AuditProperties implements Serializable { @NestedConfigurationProperty private AuditMongoDbProperties mongo = new AuditMongoDbProperties(); - /** - * Family of sub-properties pertaining to CouchDb-based audit destinations. - */ - @NestedConfigurationProperty - private AuditCouchDbProperties couchDb = new AuditCouchDbProperties(); - /** * Family of sub-properties pertaining to Redis-based audit destinations. */ @@ -72,12 +66,6 @@ public class AuditProperties implements Serializable { @NestedConfigurationProperty private AuditSlf4jLogProperties slf4j = new AuditSlf4jLogProperties(); - /** - * Family of sub-properties pertaining to couchbase-based audit destinations. - */ - @NestedConfigurationProperty - private AuditCouchbaseProperties couchbase = new AuditCouchbaseProperties(); - /** * Family of sub-properties pertaining to dynamodb-based audit destinations. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java index 3368b6c10ac4..6443a7b3027d 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/AuthenticationProperties.java @@ -5,8 +5,6 @@ import org.apereo.cas.configuration.model.support.cassandra.authentication.CassandraAuthenticationProperties; import org.apereo.cas.configuration.model.support.clouddirectory.AmazonCloudDirectoryProperties; import org.apereo.cas.configuration.model.support.cognito.AmazonCognitoAuthenticationProperties; -import org.apereo.cas.configuration.model.support.couchbase.authentication.CouchbaseAuthenticationProperties; -import org.apereo.cas.configuration.model.support.couchdb.authentication.CouchDbAuthenticationProperties; import org.apereo.cas.configuration.model.support.generic.AcceptAuthenticationProperties; import org.apereo.cas.configuration.model.support.generic.FileAuthenticationProperties; import org.apereo.cas.configuration.model.support.generic.GroovyAuthenticationProperties; @@ -124,12 +122,6 @@ public class AuthenticationProperties implements Serializable { @NestedConfigurationProperty private OktaAuthenticationProperties okta = new OktaAuthenticationProperties(); - /** - * Couchbase authentication settings. - */ - @NestedConfigurationProperty - private CouchbaseAuthenticationProperties couchbase = new CouchbaseAuthenticationProperties(); - /** * Redis authentication settings. */ @@ -285,12 +277,6 @@ public class AuthenticationProperties implements Serializable { @NestedConfigurationProperty private MongoDbAuthenticationProperties mongo = new MongoDbAuthenticationProperties(); - /** - * CouchDb authentication settings. - */ - @NestedConfigurationProperty - private CouchDbAuthenticationProperties couchDb = new CouchDbAuthenticationProperties(); - /** * OAuth authentication settings. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/PrincipalAttributesProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/PrincipalAttributesProperties.java index d52e76351bf5..e0b0ee34e109 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/PrincipalAttributesProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/authentication/PrincipalAttributesProperties.java @@ -1,7 +1,6 @@ package org.apereo.cas.configuration.model.core.authentication; import org.apereo.cas.configuration.model.support.azuread.AzureActiveDirectoryAttributesProperties; -import org.apereo.cas.configuration.model.support.couchbase.authentication.CouchbasePrincipalAttributesProperties; import org.apereo.cas.configuration.model.support.jdbc.JdbcPrincipalAttributesProperties; import org.apereo.cas.configuration.model.support.ldap.LdapPrincipalAttributesProperties; import org.apereo.cas.configuration.model.support.okta.OktaPrincipalAttributesProperties; @@ -90,12 +89,6 @@ public class PrincipalAttributesProperties implements Serializable { */ private List redis = new ArrayList<>(0); - /** - * Retrieve attributes from Couchbase repositories. - */ - @NestedConfigurationProperty - private CouchbasePrincipalAttributesProperties couchbase = new CouchbasePrincipalAttributesProperties(); - /** * Use stubbed attribute definitions as the underlying attribute repository source. * Static attributes that need to be mapped to a hardcoded value belong here. diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/CouchDbEventsProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/CouchDbEventsProperties.java deleted file mode 100644 index a41bf21d96ec..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/CouchDbEventsProperties.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.apereo.cas.configuration.model.core.events; - -import org.apereo.cas.configuration.model.support.couchdb.BaseAsynchronousCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchDbEventsProperties}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7 - */ - -@RequiresModule(name = "cas-server-support-events-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@JsonFilter("CouchDbEventsProperties") -@Deprecated(since = "7.0.0") -public class CouchDbEventsProperties extends BaseAsynchronousCouchDbProperties { - - @Serial - private static final long serialVersionUID = -1587160128953366615L; - - public CouchDbEventsProperties() { - setDbName("events"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/EventsProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/EventsProperties.java index bc48143cae20..092cd4aad5be 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/EventsProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/events/EventsProperties.java @@ -51,12 +51,6 @@ public class EventsProperties implements Serializable { @NestedConfigurationProperty private MongoDbEventsProperties mongo = new MongoDbEventsProperties(); - /** - * Track authentication events inside a couchdb instance. - */ - @NestedConfigurationProperty - private CouchDbEventsProperties couchDb = new CouchDbEventsProperties(); - /** * Track authentication events inside a DynamoDb instance. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/services/ServiceRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/services/ServiceRegistryProperties.java index 5a21dcb41f52..5f8c191f3c5f 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/services/ServiceRegistryProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/services/ServiceRegistryProperties.java @@ -4,8 +4,6 @@ import org.apereo.cas.configuration.model.support.aws.AmazonS3ServiceRegistryProperties; import org.apereo.cas.configuration.model.support.cassandra.serviceregistry.CassandraServiceRegistryProperties; import org.apereo.cas.configuration.model.support.cosmosdb.CosmosDbServiceRegistryProperties; -import org.apereo.cas.configuration.model.support.couchbase.serviceregistry.CouchbaseServiceRegistryProperties; -import org.apereo.cas.configuration.model.support.couchdb.serviceregistry.CouchDbServiceRegistryProperties; import org.apereo.cas.configuration.model.support.dynamodb.DynamoDbServiceRegistryProperties; import org.apereo.cas.configuration.model.support.email.EmailProperties; import org.apereo.cas.configuration.model.support.git.services.GitServiceRegistryProperties; @@ -63,12 +61,6 @@ public class ServiceRegistryProperties implements Serializable { @NestedConfigurationProperty private GitServiceRegistryProperties git = new GitServiceRegistryProperties(); - /** - * Properties pertaining to Cosmos DB service registry. - */ - @NestedConfigurationProperty - private CouchDbServiceRegistryProperties couchDb = new CouchDbServiceRegistryProperties(); - /** * Properties pertaining to REST service registry. */ @@ -111,12 +103,6 @@ public class ServiceRegistryProperties implements Serializable { @NestedConfigurationProperty private MongoDbServiceRegistryProperties mongo = new MongoDbServiceRegistryProperties(); - /** - * Properties pertaining to couchbase service registry. - */ - @NestedConfigurationProperty - private CouchbaseServiceRegistryProperties couchbase = new CouchbaseServiceRegistryProperties(); - /** * Properties pertaining to dynamo db service registry. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java index fed53704ddd6..1f6c20cdfbd3 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/core/ticket/registry/TicketRegistryProperties.java @@ -2,7 +2,6 @@ import org.apereo.cas.configuration.model.support.cassandra.ticketregistry.CassandraTicketRegistryProperties; import org.apereo.cas.configuration.model.support.cosmosdb.CosmosDbTicketRegistryProperties; -import org.apereo.cas.configuration.model.support.couchdb.ticketregistry.CouchDbTicketRegistryProperties; import org.apereo.cas.configuration.model.support.dynamodb.DynamoDbTicketRegistryProperties; import org.apereo.cas.configuration.model.support.hazelcast.HazelcastTicketRegistryProperties; import org.apereo.cas.configuration.model.support.ignite.IgniteProperties; @@ -96,12 +95,6 @@ public class TicketRegistryProperties implements Serializable { @NestedConfigurationProperty private InMemoryTicketRegistryProperties inMemory = new InMemoryTicketRegistryProperties(); - /** - * CouchDb registry settings. - */ - @NestedConfigurationProperty - private CouchDbTicketRegistryProperties couchDb = new CouchDbTicketRegistryProperties(); - /** * Ticket registry cleaner settings. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/AcceptableUsagePolicyProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/AcceptableUsagePolicyProperties.java index f8f759bf4745..30082c7cd42f 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/AcceptableUsagePolicyProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/AcceptableUsagePolicyProperties.java @@ -46,18 +46,6 @@ public class AcceptableUsagePolicyProperties implements Serializable { @NestedConfigurationProperty private RestAcceptableUsagePolicyProperties rest = new RestAcceptableUsagePolicyProperties(); - /** - * Control AUP via CouchDb. - */ - @NestedConfigurationProperty - private CouchDbAcceptableUsagePolicyProperties couchDb = new CouchDbAcceptableUsagePolicyProperties(); - - /** - * Control AUP via Couchbase. - */ - @NestedConfigurationProperty - private CouchbaseAcceptableUsagePolicyProperties couchbase = new CouchbaseAcceptableUsagePolicyProperties(); - /** * Control AUP via a MongoDb database resource. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchDbAcceptableUsagePolicyProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchDbAcceptableUsagePolicyProperties.java deleted file mode 100644 index ae46784ab44a..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchDbAcceptableUsagePolicyProperties.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apereo.cas.configuration.model.support.aup; - -import org.apereo.cas.configuration.model.support.couchdb.BaseAsynchronousCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchDbAcceptableUsagePolicyProperties}. - * - * @author Misagh Moayyed - * @since 6.2.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-aup-couchdb") -@Accessors(chain = true) -@Getter -@Setter -@JsonFilter("CouchDbAcceptableUsagePolicyProperties") -@Deprecated(since = "7.0.0") -public class CouchDbAcceptableUsagePolicyProperties extends BaseAsynchronousCouchDbProperties { - - @Serial - private static final long serialVersionUID = 1323894615409106853L; - - public CouchDbAcceptableUsagePolicyProperties() { - setDbName("acceptable_usage_policy"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchbaseAcceptableUsagePolicyProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchbaseAcceptableUsagePolicyProperties.java deleted file mode 100644 index 1e4b5dff4d37..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/aup/CouchbaseAcceptableUsagePolicyProperties.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.apereo.cas.configuration.model.support.aup; - -import org.apereo.cas.configuration.model.support.couchbase.BaseCouchbaseProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchbaseAcceptableUsagePolicyProperties}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7.0.0 - */ -@RequiresModule(name = "cas-server-support-aup-couchbase") -@Accessors(chain = true) -@Getter -@Setter -@JsonFilter("CouchbaseAcceptableUsagePolicyProperties") -@Deprecated(since = "7.0.0") -public class CouchbaseAcceptableUsagePolicyProperties extends BaseCouchbaseProperties { - @Serial - private static final long serialVersionUID = 2323894615409106853L; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/ConsentProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/ConsentProperties.java index f2e916af2480..fc42b9755771 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/ConsentProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/ConsentProperties.java @@ -83,12 +83,6 @@ public class ConsentProperties implements Serializable { @NestedConfigurationProperty private MongoDbConsentProperties mongo = new MongoDbConsentProperties(); - /** - * Keep consent decisions stored via a CouchDb database resource. - */ - @NestedConfigurationProperty - private CouchDbConsentProperties couchDb = new CouchDbConsentProperties(); - /** * Keep consent decisions stored via a DynamoDb database resource. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/CouchDbConsentProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/CouchDbConsentProperties.java deleted file mode 100644 index bed4338a1354..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/consent/CouchDbConsentProperties.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apereo.cas.configuration.model.support.consent; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchDbConsentProperties}. - * - * @author Misagh Moayyed - * @since 6.4.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-consent-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class CouchDbConsentProperties extends BaseCouchDbProperties { - @Serial - private static final long serialVersionUID = 8184753250455916462L; - - public CouchDbConsentProperties() { - this.setDbName("consent"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/BaseCouchbaseProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/BaseCouchbaseProperties.java deleted file mode 100644 index 7982760cb1c7..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/BaseCouchbaseProperties.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchbase; - -import org.apereo.cas.configuration.support.DurationCapable; -import org.apereo.cas.configuration.support.RequiredProperty; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; -import java.util.stream.Stream; - -/** - * This is {@link BaseCouchbaseProperties}. - * - * @author Misagh Moayyed - * @since 5.2.0 - * @deprecated Since 7.0.0 - */ -@Getter -@Setter -@Accessors(chain = true) -@RequiresModule(name = "cas-server-support-couchbase-core") -@Deprecated(since = "7.0.0") -public abstract class BaseCouchbaseProperties implements Serializable { - - @Serial - private static final long serialVersionUID = 6550895842866988551L; - - /** - * Node addresses. - */ - @RequiredProperty - private List addresses = Stream.of("localhost").toList(); - - /** - * String representation of connection timeout. - */ - @DurationCapable - private String connectionTimeout = "PT60S"; - - /** - * String representation of idle connection timeout. - */ - @DurationCapable - private String idleConnectionTimeout = "PT60S"; - - /** - * String representation of search timeout. - */ - @DurationCapable - private String searchTimeout = "PT30S"; - - /** - * String representation of query timeout. - */ - @DurationCapable - private String queryTimeout = "PT30S"; - - /** - * String representation of view timeout. - */ - @DurationCapable - private String viewTimeout = "PT30S"; - - /** - * String representation of KV timeout. - */ - @DurationCapable - private String kvTimeout = "PT30S"; - - /** - * String representation of scan timeout. - */ - @DurationCapable - private String scanWaitTimeout = "PT30S"; - - /** - * Cluster username. - */ - @RequiredProperty - private String clusterUsername; - - /** - * Cluster password. - */ - @RequiredProperty - private String clusterPassword; - - /** - * Maximum number of connections made to the cluster. - */ - private int maxHttpConnections = 5; - - /** - * Maximum number of parallel threads made for queries. - */ - private int maxParallelism; - - /** - * Allows to customize the maximum number of - * requests allowed in the retry timer. - */ - private long maxNumRequestsInRetry = 32768; - - /** - * Bucket name. - */ - @RequiredProperty - private String bucket = "testbucket"; - - /** - * Query scan consistency. - *

- * By default, the query engine will return whatever is currently in the index at - * the time of query (this mode is also called {@code NOT_BOUNDED}). If you - * need to include everything that has just been written, a different scan consistency must - * be chosen. If {@code REQUEST_PLUS} is chosen, it will likely take a bit - * longer to return the results but the query engine will make sure that it is as up-to-date as possible. - *

- * Accepted values are: {@code NOT_BOUNDED, REQUEST_PLUS}. - */ - private String scanConsistency = "NOT_BOUNDED"; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbaseAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbaseAuthenticationProperties.java deleted file mode 100644 index 9fef57a4b3b8..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbaseAuthenticationProperties.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchbase.authentication; - -import org.apereo.cas.configuration.model.core.authentication.PasswordEncoderProperties; -import org.apereo.cas.configuration.model.core.authentication.PrincipalTransformationProperties; -import org.apereo.cas.configuration.model.support.couchbase.BaseCouchbaseProperties; -import org.apereo.cas.configuration.support.RequiredProperty; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.springframework.boot.context.properties.NestedConfigurationProperty; - -import java.io.Serial; - -/** - * This is {@link CouchbaseAuthenticationProperties}. - * - * @author Misagh Moayyed - * @since 5.2.0 - * @deprecated Since 7.0.0 - */ -@Getter -@Setter -@Accessors(chain = true) -@RequiresModule(name = "cas-server-support-couchbase-authentication") -@Deprecated(since = "7.0.0") -public class CouchbaseAuthenticationProperties extends BaseCouchbaseProperties { - - @Serial - private static final long serialVersionUID = -7257332242368463818L; - - /** - * Principal transformation settings. - */ - @NestedConfigurationProperty - private PrincipalTransformationProperties principalTransformation = new PrincipalTransformationProperties(); - - /** - * The name of the authentication handler. - */ - private String name; - - /** - * Password encoder settings for this handler. - */ - @NestedConfigurationProperty - private PasswordEncoderProperties passwordEncoder = new PasswordEncoderProperties(); - - /** - * Order of authentication handler in chain. - */ - private int order = Integer.MAX_VALUE; - - /** - * Username attribute to fetch and compare against credential. - */ - @RequiredProperty - private String usernameAttribute = "username"; - - /** - * Password attribute to fetch and compare against credential. - */ - @RequiredProperty - private String passwordAttribute = "psw"; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbasePrincipalAttributesProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbasePrincipalAttributesProperties.java deleted file mode 100644 index 1db8739c988b..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/authentication/CouchbasePrincipalAttributesProperties.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchbase.authentication; - -import org.apereo.cas.configuration.model.support.couchbase.BaseCouchbaseProperties; -import org.apereo.cas.configuration.support.RequiredProperty; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchbasePrincipalAttributesProperties}. - * - * @author Misagh Moayyed - * @since 5.3.0 - * @deprecated Since 7.0.0 - */ -@RequiresModule(name = "cas-server-support-couchbase-authentication") -@Getter -@Setter -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class CouchbasePrincipalAttributesProperties extends BaseCouchbaseProperties { - @Serial - private static final long serialVersionUID = -6573755681498251678L; - - /** - * The order of this attribute repository in the chain of repositories. - * Can be used to explicitly position this source in chain and affects - * merging strategies. - */ - private int order; - - /** - * Username attribute to fetch attributes by. - */ - @RequiredProperty - private String usernameAttribute = "username"; - - /** - * A value can be assigned to this field to uniquely identify this resolver. - */ - private String id; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/serviceregistry/CouchbaseServiceRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/serviceregistry/CouchbaseServiceRegistryProperties.java deleted file mode 100644 index 513e7d7c6af7..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchbase/serviceregistry/CouchbaseServiceRegistryProperties.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchbase.serviceregistry; - -import org.apereo.cas.configuration.model.support.couchbase.BaseCouchbaseProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchbaseServiceRegistryProperties}. - * - * @author Misagh Moayyed - * @since 5.0.0 - * @deprecated Since 7.0.0 - */ -@RequiresModule(name = "cas-server-support-couchbase-service-registry") -@Getter -@Setter -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class CouchbaseServiceRegistryProperties extends BaseCouchbaseProperties { - @Serial - private static final long serialVersionUID = -4975171412161962007L; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseAsynchronousCouchDbProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseAsynchronousCouchDbProperties.java deleted file mode 100644 index 89c6e64f009e..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseAsynchronousCouchDbProperties.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchdb; - -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link BaseAsynchronousCouchDbProperties}. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@Getter -@Setter -@Accessors(chain = true) -@RequiresModule(name = "cas-server-support-couchdb-core") -public abstract class BaseAsynchronousCouchDbProperties extends BaseCouchDbProperties { - - @Serial - private static final long serialVersionUID = -7920471433876478891L; - - /** - * Make DB updates asynchronously. - */ - private boolean asynchronous = true; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseCouchDbProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseCouchDbProperties.java deleted file mode 100644 index f18c4bfcd4a1..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/BaseCouchDbProperties.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchdb; - -import org.apereo.cas.configuration.support.RequiredProperty; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; -import java.io.Serializable; - -/** - * This is {@link BaseCouchDbProperties}. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@Getter -@Setter -@RequiresModule(name = "cas-server-support-couchdb-core") -@Accessors(chain = true) -public abstract class BaseCouchDbProperties implements Serializable { - - @Serial - private static final long serialVersionUID = 1323894615409106853L; - - /** - * Connection url. - */ - @RequiredProperty - private String url = "http://localhost:5984"; - - /** - * Username for connection. - */ - @RequiredProperty - private String username; - - /** - * Password for connection. - */ - @RequiredProperty - private String password; - - /** - * Socket idle timeout. - */ - private int socketTimeout = 10000; - - /** - * TCP connection timeout. - */ - private int connectionTimeout = 1000; - - /** - * Maximum connections to CouchDB. - */ - private int maxConnections = 20; - - /** - * Use TLS. Only needed if not specified by URL. - */ - private boolean enableSsl; - - /** - * Relax TLS settings–like certificate verification. - */ - private boolean relaxedSslSettings; - - /** - * Use a local cache to reduce fetches.. - */ - private boolean caching; - - /** - * Max entries in local cache. - */ - private int maxCacheEntries = 1000; - - /** - * Largest allowable serialized object. - */ - private int maxObjectSizeBytes = 8192; - - /** - * Expect HTTP 100 Continue during connection. - */ - private boolean useExpectContinue = true; - - /** - * Remove idle connections from pool. - */ - private boolean cleanupIdleConnections = true; - - /** - * Create the database if it doesn't exist. - */ - private boolean createIfNotExists = true; - - /** - * Retries for update conflicts. - */ - private int retries = 5; - - /** - * Database name. - */ - @RequiredProperty - private String dbName; - - /** - * Proxy host. - */ - private String proxyHost; - - /** - * proxy port. - */ - private int proxyPort = -1; -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/authentication/CouchDbAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/authentication/CouchDbAuthenticationProperties.java deleted file mode 100644 index e0418228f13d..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/authentication/CouchDbAuthenticationProperties.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchdb.authentication; - -import org.apereo.cas.configuration.model.core.authentication.PasswordEncoderProperties; -import org.apereo.cas.configuration.model.core.authentication.PrincipalTransformationProperties; -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiredProperty; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.springframework.boot.context.properties.NestedConfigurationProperty; - -import java.io.Serial; - -/** - * This is {@link CouchDbAuthenticationProperties}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@Setter -@RequiresModule(name = "cas-server-support-couchdb-authentication") -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class CouchDbAuthenticationProperties extends BaseCouchDbProperties { - - @Serial - private static final long serialVersionUID = 1830797033934229732L; - - /** - * Principal transformation settings. - */ - @NestedConfigurationProperty - private PrincipalTransformationProperties principalTransformation = new PrincipalTransformationProperties(); - - /** - * Attributes to fetch from CouchDb. - */ - private String attributes; - - /** - * The name of the authentication handler. - */ - private String name; - - /** - * Password encoder settings for this handler. - */ - @NestedConfigurationProperty - private PasswordEncoderProperties passwordEncoder = new PasswordEncoderProperties(); - - /** - * Order of authentication handler in chain. - */ - private int order = Integer.MAX_VALUE; - - /** - * Username attribute to fetch and compare against credential. - */ - @RequiredProperty - private String usernameAttribute = "username"; - - /** - * Password attribute to fetch and compare against credential. - */ - @RequiredProperty - private String passwordAttribute = "password"; - - public CouchDbAuthenticationProperties() { - setDbName("users"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/serviceregistry/CouchDbServiceRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/serviceregistry/CouchDbServiceRegistryProperties.java deleted file mode 100644 index 781230a27c88..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/serviceregistry/CouchDbServiceRegistryProperties.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchdb.serviceregistry; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchDbServiceRegistryProperties}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-couchdb-service-registry") -@Accessors(chain = true) -@Getter -@Setter -@JsonFilter("CouchDbServiceRegistryProperties") -@Deprecated(since = "7.0.0") -public class CouchDbServiceRegistryProperties extends BaseCouchDbProperties { - @Serial - private static final long serialVersionUID = -5101551655756163621L; - - public CouchDbServiceRegistryProperties() { - this.setDbName("service_registry"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/ticketregistry/CouchDbTicketRegistryProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/ticketregistry/CouchDbTicketRegistryProperties.java deleted file mode 100644 index caa11be1c1e9..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/couchdb/ticketregistry/CouchDbTicketRegistryProperties.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.apereo.cas.configuration.model.support.couchdb.ticketregistry; - -import org.apereo.cas.configuration.model.core.util.EncryptionRandomizedSigningJwtCryptographyProperties; -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.springframework.boot.context.properties.NestedConfigurationProperty; - -import java.io.Serial; - -/** - * This is {@link CouchDbTicketRegistryProperties}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-couchdb-ticket-registry") -@Getter -@Setter -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class CouchDbTicketRegistryProperties extends BaseCouchDbProperties { - @Serial - private static final long serialVersionUID = 6895485069081125319L; - - /** - * Crypto settings for the registry. - */ - @NestedConfigurationProperty - private EncryptionRandomizedSigningJwtCryptographyProperties crypto = new EncryptionRandomizedSigningJwtCryptographyProperties(); - - public CouchDbTicketRegistryProperties() { - this.crypto.setEnabled(false); - this.setDbName("ticket_registry"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/CouchDbGoogleAuthenticatorMultifactorProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/CouchDbGoogleAuthenticatorMultifactorProperties.java deleted file mode 100644 index 17490069c863..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/CouchDbGoogleAuthenticatorMultifactorProperties.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apereo.cas.configuration.model.support.mfa.gauth; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchDbGoogleAuthenticatorMultifactorProperties}. - * - * @author Misagh Moayyed - * @since 5.2.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-gauth-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@JsonFilter("CouchDbGoogleAuthenticatorMultifactorProperties") -@Deprecated(since = "7.0.0") -public class CouchDbGoogleAuthenticatorMultifactorProperties extends BaseCouchDbProperties { - - @Serial - private static final long serialVersionUID = -6260683393319585262L; - - public CouchDbGoogleAuthenticatorMultifactorProperties() { - setDbName("gauth_multifactor"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/GoogleAuthenticatorMultifactorProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/GoogleAuthenticatorMultifactorProperties.java index 22d18cd133b6..37f7b885170d 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/GoogleAuthenticatorMultifactorProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/gauth/GoogleAuthenticatorMultifactorProperties.java @@ -77,12 +77,6 @@ public class GoogleAuthenticatorMultifactorProperties extends BaseMultifactorAut @NestedConfigurationProperty private RestfulGoogleAuthenticatorMultifactorProperties rest = new RestfulGoogleAuthenticatorMultifactorProperties(); - /** - * Store google authenticator devices via CouchDb. - */ - @NestedConfigurationProperty - private CouchDbGoogleAuthenticatorMultifactorProperties couchDb = new CouchDbGoogleAuthenticatorMultifactorProperties(); - /** * Store google authenticator devices via Redis. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/CouchDbTrustedDevicesMultifactorProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/CouchDbTrustedDevicesMultifactorProperties.java deleted file mode 100644 index 5a088305484f..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/CouchDbTrustedDevicesMultifactorProperties.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apereo.cas.configuration.model.support.mfa.trusteddevice; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link CouchDbTrustedDevicesMultifactorProperties}. - * - * @author Misagh Moayyed - * @since 6.4.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-trusted-mfa-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@JsonFilter("CouchDbTrustedDevicesMultifactorProperties") -@Deprecated(since = "7.0.0") -public class CouchDbTrustedDevicesMultifactorProperties extends BaseCouchDbProperties { - - @Serial - private static final long serialVersionUID = 5887850351177564308L; - - public CouchDbTrustedDevicesMultifactorProperties() { - setDbName("trusted_devices_multifactor"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/TrustedDevicesMultifactorProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/TrustedDevicesMultifactorProperties.java index 2e7732481759..667f2e844f02 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/TrustedDevicesMultifactorProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/trusteddevice/TrustedDevicesMultifactorProperties.java @@ -73,12 +73,6 @@ public class TrustedDevicesMultifactorProperties implements Serializable { @NestedConfigurationProperty private MongoDbTrustedDevicesMultifactorProperties mongo = new MongoDbTrustedDevicesMultifactorProperties(); - /** - * Store devices records inside CouchDb. - */ - @NestedConfigurationProperty - private CouchDbTrustedDevicesMultifactorProperties couchDb = new CouchDbTrustedDevicesMultifactorProperties(); - /** * Store devices records inside DynamoDb. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FCouchDbMultifactorAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FCouchDbMultifactorAuthenticationProperties.java deleted file mode 100644 index a9af4220c6f3..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FCouchDbMultifactorAuthenticationProperties.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apereo.cas.configuration.model.support.mfa.u2f; - -import org.apereo.cas.configuration.model.support.couchdb.BaseAsynchronousCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link U2FCouchDbMultifactorAuthenticationProperties}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-u2f-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@JsonFilter("U2FCouchDbMultifactorAuthenticationProperties") -@Deprecated(since = "7.0.0") -public class U2FCouchDbMultifactorAuthenticationProperties extends BaseAsynchronousCouchDbProperties { - - @Serial - private static final long serialVersionUID = 2751957521987245445L; - - public U2FCouchDbMultifactorAuthenticationProperties() { - setDbName("u2f_multifactor"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FMultifactorAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FMultifactorAuthenticationProperties.java index 432a48913e06..d3f9a2cc361b 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FMultifactorAuthenticationProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/u2f/U2FMultifactorAuthenticationProperties.java @@ -82,13 +82,7 @@ public class U2FMultifactorAuthenticationProperties extends BaseMultifactorAuthe */ @NestedConfigurationProperty private U2FRestfulMultifactorAuthenticationProperties rest = new U2FRestfulMultifactorAuthenticationProperties(); - - /** - * Store device registration records via CouchDb. - */ - @NestedConfigurationProperty - private U2FCouchDbMultifactorAuthenticationProperties couchDb = new U2FCouchDbMultifactorAuthenticationProperties(); - + /** * Clean up expired records via a background cleaner process. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyCouchDbMultifactorProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyCouchDbMultifactorProperties.java deleted file mode 100644 index ce6b1f6b872d..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyCouchDbMultifactorProperties.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apereo.cas.configuration.model.support.mfa.yubikey; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link YubiKeyCouchDbMultifactorProperties}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-yubikey-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class YubiKeyCouchDbMultifactorProperties extends BaseCouchDbProperties { - @Serial - private static final long serialVersionUID = 3757390989294642185L; - - public YubiKeyCouchDbMultifactorProperties() { - this.setDbName("yubikey"); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyMultifactorAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyMultifactorAuthenticationProperties.java index 0a42b906022d..466f2168d94c 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyMultifactorAuthenticationProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/mfa/yubikey/YubiKeyMultifactorAuthenticationProperties.java @@ -85,12 +85,6 @@ public class YubiKeyMultifactorAuthenticationProperties extends BaseMultifactorA */ private boolean trustedDeviceEnabled; - /** - * Keep device registration records inside a CouchDb resource. - */ - @NestedConfigurationProperty - private YubiKeyCouchDbMultifactorProperties couchDb = new YubiKeyCouchDbMultifactorProperties(); - /** * Keep device registration records inside a JDBC resource. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/CouchDbSamlMetadataProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/CouchDbSamlMetadataProperties.java deleted file mode 100644 index 33a8c7a7bcc4..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/CouchDbSamlMetadataProperties.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.apereo.cas.configuration.model.support.saml.idp.metadata; - -import org.apereo.cas.configuration.model.core.util.EncryptionJwtSigningJwtCryptographyProperties; -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; -import org.apereo.cas.util.crypto.CipherExecutor; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.springframework.boot.context.properties.NestedConfigurationProperty; - -import java.io.Serial; - -/** - * Configuration properties class for saml metadata based on CouchDB. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-saml-idp-metadata-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@JsonFilter("CouchDbSamlMetadataProperties") -@Deprecated(since = "7.0.0") -public class CouchDbSamlMetadataProperties extends BaseCouchDbProperties { - - @Serial - private static final long serialVersionUID = 1673956475847790139L; - - /** - * Whether identity provider metadata artifacts - * are expected to be found in the database. - */ - private boolean idpMetadataEnabled; - - /** - * Crypto settings that sign/encrypt the metadata records. - */ - @NestedConfigurationProperty - private EncryptionJwtSigningJwtCryptographyProperties crypto = new EncryptionJwtSigningJwtCryptographyProperties(); - - public CouchDbSamlMetadataProperties() { - setDbName("saml_metadata"); - crypto.getEncryption().setKeySize(CipherExecutor.DEFAULT_STRINGABLE_ENCRYPTION_KEY_SIZE); - crypto.getSigning().setKeySize(CipherExecutor.DEFAULT_STRINGABLE_SIGNING_KEY_SIZE); - } -} diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/SamlIdPMetadataProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/SamlIdPMetadataProperties.java index 62323f597e9c..82651e8b202e 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/SamlIdPMetadataProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/saml/idp/metadata/SamlIdPMetadataProperties.java @@ -84,12 +84,6 @@ public class SamlIdPMetadataProperties implements Serializable { @NestedConfigurationProperty private AmazonS3SamlMetadataProperties amazonS3 = new AmazonS3SamlMetadataProperties(); - /** - * Properties pertaining to CouchDB metadata resolution. - */ - @NestedConfigurationProperty - private CouchDbSamlMetadataProperties couchDb = new CouchDbSamlMetadataProperties(); - /** * Metadata management settings via MDQ protocol. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateAuthenticationProperties.java index 1a0c52f0aef9..2f48c607f3ff 100644 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateAuthenticationProperties.java +++ b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateAuthenticationProperties.java @@ -35,12 +35,6 @@ public class SurrogateAuthenticationProperties implements Serializable { */ private String separator = "+"; - /** - * Locate surrogate accounts via CouchDB. - */ - @NestedConfigurationProperty - private SurrogateCouchDbAuthenticationProperties couchDb = new SurrogateCouchDbAuthenticationProperties(); - /** * Locate surrogate accounts via CAS configuration, hardcoded as properties. */ diff --git a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateCouchDbAuthenticationProperties.java b/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateCouchDbAuthenticationProperties.java deleted file mode 100644 index e787228a7a97..000000000000 --- a/api/cas-server-core-api-configuration-model/src/main/java/org/apereo/cas/configuration/model/support/surrogate/SurrogateCouchDbAuthenticationProperties.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.apereo.cas.configuration.model.support.surrogate; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; -import org.apereo.cas.configuration.support.RequiresModule; - -import com.fasterxml.jackson.annotation.JsonFilter; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.io.Serial; - -/** - * This is {@link SurrogateCouchDbAuthenticationProperties}. - * - * @author Misagh Moayyed - * @since 5.1.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-surrogate-authentication-couchdb") -@Getter -@Setter -@Accessors(chain = true) -@JsonFilter("SurrogateCouchDbAuthenticationProperties") -@Deprecated(since = "7.0.0") -public class SurrogateCouchDbAuthenticationProperties extends BaseCouchDbProperties { - - @Serial - private static final long serialVersionUID = 8378399979559955402L; - - /** - * Use user profiles instead of surrogate/principal pairs. If +true+, a list of of - * principals the user is an authorized surrogate of is stored in the - * user profile in CouchDb. Most useful with CouchDb authentication or AUP. - */ - private boolean profileBased; - - /** - * Attribute with list of principals the user may surrogate - * when user surrogates are stored in user profiles. - */ - private String surrogatePrincipalsAttribute = "surrogateFor"; - - public SurrogateCouchDbAuthenticationProperties() { - this.setDbName("surrogates"); - } -} diff --git a/ci/tests/couchbase/run-couchbase-server.sh b/ci/tests/couchbase/run-couchbase-server.sh deleted file mode 100755 index 75dcb6b1aa6b..000000000000 --- a/ci/tests/couchbase/run-couchbase-server.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/bash - -# while sleep 9m; do echo -e '\n=====[ Gradle build is still running ]====='; done & -function configureNode() { - echo -e "\n*************************************************************" - echo -e "Setting default memory quota for the pool" - echo -e "*************************************************************" - curl http://localhost:8091/pools/default -d memoryQuota=1024 | jq - - echo -e "\n*************************************************************" - echo -e "Initialize node..." - echo -e "*************************************************************" - curl http://localhost:8091/nodes/self/controller/settings \ - -d path=/opt/couchbase/var/lib/couchbase/data \ - -d index_path=/opt/couchbase/var/lib/couchbase/data | jq - - echo -e "*************************************************************" - echo -e "Rename node..." - echo -e "*************************************************************" - curl http://localhost:8091/node/controller/rename -d hostname=127.0.0.1 | jq -} - -function loadBuckets() { - echo -e "\n*************************************************************" - echo -e "Loading Couchbase buckets..." - echo -e "*************************************************************" - curl -u 'admin:password' http://localhost:8091/pools/default/buckets | jq -} - -function createBuckets() { - echo -e "\n*************************************************************" - echo -e "Creating Couchbase buckets..." - echo -e "*************************************************************" - - echo -e "Creating Couchbase testbucket bucket..." - curl -u 'admin:password' -d 'name=testbucket' -d 'bucketType=couchbase' \ - -d 'ramQuotaMB=220' -d 'authType=sasl' -d 'saslPassword=password' \ - http://localhost:8091/pools/default/buckets | jq - - echo -e "Creating Couchbase pplbucket bucket..." - curl -u 'admin:password' -d 'name=pplbucket' -d 'bucketType=couchbase' \ - -d 'ramQuotaMB=220' -d 'authType=sasl' -d 'saslPassword=password' http://localhost:8091/pools/default/buckets | jq - - echo -e "Creating Couchbase casbucket bucket..." - curl -u 'admin:password' -d 'name=casbucket' -d 'bucketType=couchbase' \ - -d 'ramQuotaMB=120' -d authType='none' http://localhost:8091/pools/default/buckets | jq -} - -function populateBuckets() { - echo -e "\n*************************************************************" - echo -e "Creating document/accounts..." - echo -e "*************************************************************" - curl -u 'admin:password' http://localhost:8093/query/service \ - -d 'statement=INSERT INTO `pplbucket` (KEY,VALUE) VALUES("accounts", {"username": "casuser", "psw": "Mellon", "firstname": "CAS", "lastname":"User"})' | jq - - curl -u 'admin:password' http://localhost:8093/query/service \ - -d 'statement=INSERT INTO `pplbucket` (KEY,VALUE) VALUES("bad-accounts", {"username": "nopsw", "firstname": "hello", "lastname":"world"})' | jq -} - -function createIndex() { - echo -e "\n*************************************************************" - echo -e "Creating index settings..." - echo -e "*************************************************************" - curl -u 'admin:password' 'http://localhost:8091/settings/indexes' -d 'indexerThreads=0' -d 'logLevel=info' \ - -d 'maxRollbackPoints=5' -d 'memorySnapshotInterval=200' \ - -d 'stableSnapshotInterval=5000' -d 'storageMode=memory_optimized' | jq - sleep 10 - - echo -e "\n*************************************************************" - echo -e "Creating index..." - echo -e "*************************************************************" - curl -u 'admin:password' http://localhost:8093/query/service \ - -d 'statement=CREATE INDEX accounts_idx ON testbucket(username)' -d 'namespace=default' | jq - sleep 10 - curl -u 'admin:password' http://localhost:8093/query/service \ - -d 'statement=CREATE INDEX accounts_idx ON pplbucket(username)' -d 'namespace=default' | jq - sleep 10 -} - -function createPrimaryIndex() { - echo -e "\n*************************************************************" - echo -e "Creating primary index..." - echo -e "*************************************************************" - curl -u 'admin:password' http://localhost:8093/query/service -d 'statement=CREATE PRIMARY INDEX `primary-idx` ON `testbucket`' -d 'namespace=default' | jq - sleep 5 - curl -u 'admin:password' http://localhost:8093/query/service -d 'statement=CREATE PRIMARY INDEX `primary-idx` ON `pplbucket`' -d 'namespace=default' | jq - sleep 5 - curl -u 'admin:password' http://localhost:8093/query/service -d 'statement=CREATE PRIMARY INDEX `primary-idx` ON `casbucket`' -d 'namespace=default' | jq - sleep 5 -} - -echo "Running Couchbase docker image..." -docker stop couchbase || true && docker rm couchbase || true -docker run --rm -d --name couchbase -p 8091-8094:8091-8094 -p 11210:11210 couchbase/server:7.1.3 -echo "Waiting for Couchbase server to come online..." -sleep 20 -until $(curl --output /dev/null --silent --head --fail http://localhost:8091); do - printf '.' - sleep 1 -done - -configureNode - -echo -e "\n*************************************************************" -echo -e "Setting cluster services..." -echo -e "*************************************************************" -curl http://localhost:8091/node/controller/setupServices -d 'services=kv%2Cn1ql%2Cindex' - -echo -e "\n*************************************************************" -echo -e "Setup Administrator username and password..." -echo -e "*************************************************************" -curl http://localhost:8091/settings/web -d password=password -d username=admin -d port=8091 -d roles=full_admin - -createBuckets -loadBuckets -createIndex -populateBuckets -sleep 5 -createPrimaryIndex - -docker ps | grep "couchbase" -retVal=$? -if [ $retVal == 0 ]; then - echo "Couchbase docker container is running." -else - echo "Couchbase docker container failed to start." - exit $retVal -fi diff --git a/ci/tests/couchdb/run-couchdb-server.sh b/ci/tests/couchdb/run-couchdb-server.sh deleted file mode 100755 index a4a0058710f8..000000000000 --- a/ci/tests/couchdb/run-couchdb-server.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - - -# while sleep 9m; do echo -e '\n=====[ Gradle build is still running ]====='; done & - -echo "Running CouchDb docker image..." -docker stop couchdb-server || true && docker rm couchdb-server || true -docker run --rm -d -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password \ - -p 5984:5984 -p 9100:9100 -p 3469:4369 --name="couchdb-server" apache/couchdb:3.3.0 - -docker ps | grep "couchdb-server" -retVal=$? -if [ $retVal == 0 ]; then - echo "CouchDb docker container is running." -else - echo "CouchDb docker container failed to start." - exit $retVal -fi - -echo "Waiting for CouchDb server to come online..." -sleep 10 -until curl -u admin:password --output /dev/null --silent --fail http://localhost:5984/_membership; do - printf '.' - sleep 1 -done - -curl -u admin:password -X PUT http://127.0.0.1:5984/_node/nonode@nohost/_config/admins/cas -d '"password"' --fail --output /dev/null -curl -u admin:password -X PUT http://cas:password@127.0.0.1:5984/_users --fail --output /dev/null -curl -u admin:password -X PUT http://cas:password@127.0.0.1:5984/_replicator --fail --output /dev/null -curl -u admin:password -X PUT http://cas:password@127.0.0.1:5984/_global_changes --fail --output /dev/null - -retVal=$? -if [ $retVal == 0 ]; then - echo "CouchDb admin initialized." -else - echo "CouchDb admin failed to initialize." - exit $retVal -fi diff --git a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java index a7add853039b..d79cfb094f1d 100644 --- a/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java +++ b/core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationBuilder.java @@ -180,9 +180,7 @@ public AuthenticationBuilder setWarnings(final List warning) @Override @CanIgnoreReturnValue public AuthenticationBuilder addAttribute(final String key, final List value) { - if (value != null && !value.isEmpty()) { - this.attributes.put(key, value); - } + this.attributes.put(key, value); return this; } diff --git a/docs/cas-server-documentation/audits/Audits-CouchDb.md b/docs/cas-server-documentation/audits/Audits-CouchDb.md deleted file mode 100644 index 75134ad01a5f..000000000000 --- a/docs/cas-server-documentation/audits/Audits-CouchDb.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: default -title: CAS - Audit Configuration -category: Logs & Audits ---- -{% include variables.html %} - -# CouchDb Audits - -If you intend to use a CouchDb database for auditing functionality, enable the following module in your configuration: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-audit-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- - -{% include_cached casproperties.html properties="cas.audit.couch-db" %} diff --git a/docs/cas-server-documentation/audits/Audits-Couchbase.md b/docs/cas-server-documentation/audits/Audits-Couchbase.md deleted file mode 100644 index a36f116b72a0..000000000000 --- a/docs/cas-server-documentation/audits/Audits-Couchbase.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: default -title: CAS - Audit Configuration -category: Logs & Audits ---- -{% include variables.html %} - -# Couchbase Audits - -If you intend to use a Couchbase database for auditing functionality, enable the following module in your configuration: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-audit-couchbase" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.audit.couchbase" %} diff --git a/docs/cas-server-documentation/audits/Audits.md b/docs/cas-server-documentation/audits/Audits.md index 259996d9f5f6..fabf08550d7d 100644 --- a/docs/cas-server-documentation/audits/Audits.md +++ b/docs/cas-server-documentation/audits/Audits.md @@ -36,8 +36,6 @@ Audits can be managed via the following strategies. | JPA | [See this guide](Audits-Database.html). | | MongoDb | [See this guide](Audits-MongoDb.html). | | Redis | [See this guide](Audits-Redis.html). | -| ~~CouchDb~~ | [See this guide](Audits-CouchDb.html). | -| Couchbase | [See this guide](Audits-Couchbase.html). | | DynamoDb | [See this guide](Audits-DynamoDb.html). | | REST | [See this guide](Audits-REST.html). | diff --git a/docs/cas-server-documentation/authentication/Configuring-Authentication-Events-CouchDb.md b/docs/cas-server-documentation/authentication/Configuring-Authentication-Events-CouchDb.md deleted file mode 100644 index 553223a43040..000000000000 --- a/docs/cas-server-documentation/authentication/Configuring-Authentication-Events-CouchDb.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: default -title: CAS - Configuring Authentication Events -category: Authentication ---- -{% include variables.html %} - -# CouchDb Authentication Events - -Stores authentication events inside a CouchDb instance. - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-events-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.events.couch-db" %} - diff --git a/docs/cas-server-documentation/authentication/Configuring-Authentication-Events.md b/docs/cas-server-documentation/authentication/Configuring-Authentication-Events.md index 48b01e8be845..73080b979870 100644 --- a/docs/cas-server-documentation/authentication/Configuring-Authentication-Events.md +++ b/docs/cas-server-documentation/authentication/Configuring-Authentication-Events.md @@ -65,7 +65,6 @@ The following options may be used to store events in CAS. | MongoDb | [See this guide](Configuring-Authentication-Events-MongoDb.html). | | DynamoDb | [See this guide](Configuring-Authentication-Events-DynamoDb.html). | | Redis | [See this guide](Configuring-Authentication-Events-Redis.html). | -| ~~CouchDb~~ | [See this guide](Configuring-Authentication-Events-CouchDb.html). | | JPA | [See this guide](Configuring-Authentication-Events-JPA.html). | | InfluxDb | [See this guide](Configuring-Authentication-Events-InfluxDb.html). | | Memory | [See this guide](Configuring-Authentication-Events-Memory.html). | diff --git a/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling-CouchDb.md b/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling-CouchDb.md deleted file mode 100644 index 3d68e100b443..000000000000 --- a/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling-CouchDb.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: default -title: CAS - Configuring Authentication Throttling -category: Authentication ---- -{% include variables.html %} - -# CouchDb Throttling Authentication Attempts - -Queries a CouchDb data source used by the CAS audit facility to prevent successive failed login attempts -for a particular username from the same IP address. This component requires and -depends on the [CAS auditing functionality](../audits/Audits.html) via CouchDb. - -Enable the following module in your configuration overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-throttle-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.audit.couch-db" %} - -When using this feature the audit facility should be in synchronous mode. For additional instructions -on how to configure auditing, please [review the following guide](../audits/Audits.html). diff --git a/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling.md b/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling.md index cbd27a53120d..f5bc3d94cd95 100644 --- a/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling.md +++ b/docs/cas-server-documentation/authentication/Configuring-Authentication-Throttling.md @@ -72,7 +72,6 @@ The following throttling strategies are offered by CAS. | MongoDb | [See this guide](Configuring-Authentication-Throttling-MongoDb.html). | Redis | [See this guide](Configuring-Authentication-Throttling-Redis.html). | Hazelcast | [See this guide](Configuring-Authentication-Throttling-Hazelcast.html). -| CouchDb | [See this guide](Configuring-Authentication-Throttling-CouchDb.html). ## High Availability diff --git a/docs/cas-server-documentation/authentication/CouchDb-Authentication.md b/docs/cas-server-documentation/authentication/CouchDb-Authentication.md deleted file mode 100644 index d585895448b5..000000000000 --- a/docs/cas-server-documentation/authentication/CouchDb-Authentication.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: default -title: CAS - CouchDb Authentication -category: Authentication ---- - -{% include variables.html %} - -# CouchDb Authentication - -Verify and authenticate credentials against a [CouchDb](http://couchdb.apache.org/) instance -via pac4j. CAS will automatically create the design documents required by pac4j. -Support is enabled by including the following dependency in the WAR overlay: - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-couchdb-authentication" %} - -{% include_cached casproperties.html properties="cas.authn.couch-db" %} diff --git a/docs/cas-server-documentation/authentication/Couchbase-Authentication.md b/docs/cas-server-documentation/authentication/Couchbase-Authentication.md deleted file mode 100644 index b77be6622757..000000000000 --- a/docs/cas-server-documentation/authentication/Couchbase-Authentication.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: default -title: CAS - Couchbase Authentication -category: Authentication ---- -{% include variables.html %} - - -# Couchbase Authentication - -Verify and authenticate credentials using [Couchbase](http://www.couchbase.com/). - -Support is enabled by including the following dependency in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-couchbase-authentication" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.couchbase" %} - -## Couchbase Principal Attributes - -The above dependency may also be used, in the event that principal attributes -need to be fetched from a Couchbase database without necessarily authenticating credentials against Couchbase. - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.attribute-repository.couchbase" %} diff --git a/docs/cas-server-documentation/authentication/Surrogate-Authentication-Storage-CouchDb.md b/docs/cas-server-documentation/authentication/Surrogate-Authentication-Storage-CouchDb.md deleted file mode 100644 index 3365b0c4971f..000000000000 --- a/docs/cas-server-documentation/authentication/Surrogate-Authentication-Storage-CouchDb.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: default -title: CAS - Surrogate Authentication -category: Authentication ---- -{% include variables.html %} - - -# CouchDb Surrogate Authentication - -CouchDb support for surrogate authentication is enabled by including the following dependencies in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-surrogate-authentication-couchdb" %} - -Surrogate accounts may also be retrieved from an CouchDb instance. By default, this takes -the form of surrogate/principal key/value pairs. Users authorized as surrogates may be -listed multiple times to authorize them to access multiple accounts. - -{% include_cached casproperties.html properties="cas.authn.surrogate.couch-db" %} diff --git a/docs/cas-server-documentation/authentication/Surrogate-Authentication.md b/docs/cas-server-documentation/authentication/Surrogate-Authentication.md index 84202b8a7791..59972ad78f2e 100644 --- a/docs/cas-server-documentation/authentication/Surrogate-Authentication.md +++ b/docs/cas-server-documentation/authentication/Surrogate-Authentication.md @@ -43,7 +43,6 @@ Surrogate accounts may be defined statically in the CAS configuration. |-------------|------------------------------------------------------------------| | JSON | [See this guide](Surrogate-Authentication-Storage-JSON.html). | | LDAP | [See this guide](Surrogate-Authentication-Storage-LDAP.html). | -| ~~CouchDb~~ | [See this guide](Surrogate-Authentication-Storage-CouchDb.html). | | JDBC | [See this guide](Surrogate-Authentication-Storage-JDBC.html). | | REST | [See this guide](Surrogate-Authentication-Storage-REST.html). | | Groovy | [See this guide](Surrogate-Authentication-Storage-Groovy.html). | diff --git a/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata-CouchDb.md b/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata-CouchDb.md deleted file mode 100644 index b63239c51b1d..000000000000 --- a/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata-CouchDb.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -layout: default -title: CAS - SAML2 Metadata Management -category: Protocols ---- - -{% include variables.html %} - -# CouchDb - SAML2 Metadata Management - -Metadata documents may also be stored in and fetched from a NoSQL database. This may specially be used to avoid -copying metadata files across CAS nodes in a cluster, particularly where one needs to deal with more than a -few bilateral SAML integrations. Metadata documents are stored in and fetched from a single pre-defined -table (i.e. `SamlMetadataDocument`) whose connection information is taught to CAS via settings and -is automatically generated. The outline of the database document is as follows: - -| Field | Description | -|-------------|-----------------------------------------------------------------------| -| `id` | The identifier of the record. | -| `name` | Indexed field which describes and names the metadata briefly. | -| `value` | The XML document representing the metadata for the service provider. | -| `signature` | The contents of the signing certificate to validate metadata, if any. | - -Support is enabled by including the following module in the overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-saml-idp-metadata-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -SAML service definitions must then be designed as follows to allow CAS to fetch metadata documents from CouchDb instances: - -```json -{ - "@class" : "org.apereo.cas.support.saml.services.SamlRegisteredService", - "serviceId" : "the-entity-id-of-the-sp", - "name" : "SAMLService", - "id" : 10000003, - "description" : "A relational-db-based metadata resolver", - "metadataLocation" : "couchdb://", -} -``` - -
:information_source: Metadata Location

-The metadata location in the registration record above needs to be specified as couchdb:// -to signal to CAS that SAML metadata for registered service provider must be fetched from CouchDb as defined in CAS configuration. -

- -{% include_cached casproperties.html properties="cas.authn.saml-idp.metadata.couch-db" %} - -## Identity Provider Metadata - -Metadata artifacts that belong to CAS as a SAML2 identity provider may also be managed -and stored via CouchDb. Artifacts such as the metadata, signing and encryption keys, etc are kept -inside a database with documents that would have the following structure: - -| Field | Description | -|-------------------------|-----------------------------------------------------------------| -| `id` | The identifier of the record. | -| `signingCertificate` | The signing certificate. | -| `signingKey` | The signing key. | -| `encryptionCertificate` | The encryption certificate. | -| `encryptionKey` | The encryption key. | -| `metadata` | The SAML2 identity provider metadata. | -| `appliesTo` | The owner of the SAML2 identity provider metadata (i.e. `CAS`). | - -## Per Service - -Identity provider metadata, certificates and keys can also be defined on a per-service basis to override the global defaults. -Metadata documents that would be applicable to a service definition need to adjust the `appliesTo` field in the metadata -document to carry the service definition's name and numeric identifier using the `[service-name]_[service-numeric-identifier]` format. - - diff --git a/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata.md b/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata.md index 9562404e87ce..ef40bbdfc988 100644 --- a/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata.md +++ b/docs/cas-server-documentation/installation/Configuring-SAML2-DynamicMetadata.md @@ -57,7 +57,6 @@ Service provider or identity provider metadata can also be managed using any one | MongoDb | [See this guide](Configuring-SAML2-DynamicMetadata-MongoDb.html). | | Redis | [See this guide](Configuring-SAML2-DynamicMetadata-Redis.html). | | JPA | [See this guide](Configuring-SAML2-DynamicMetadata-JPA.html). | -| ~~CouchDb~~ | [See this guide](Configuring-SAML2-DynamicMetadata-CouchDb.html). | | Groovy | [See this guide](Configuring-SAML2-DynamicMetadata-Groovy.html). | | Amazon S3 | [See this guide](Configuring-SAML2-DynamicMetadata-AmazonS3.html). | diff --git a/docs/cas-server-documentation/installation/SAML2-ServiceProvider-Metadata.md b/docs/cas-server-documentation/installation/SAML2-ServiceProvider-Metadata.md index c3b13a898f92..a151a4fa3f2b 100644 --- a/docs/cas-server-documentation/installation/SAML2-ServiceProvider-Metadata.md +++ b/docs/cas-server-documentation/installation/SAML2-ServiceProvider-Metadata.md @@ -194,6 +194,5 @@ Service provider metadata can also be managed using any one of the following str | MongoDb | [See this guide](Configuring-SAML2-DynamicMetadata-MongoDb.html). | | Redis | [See this guide](Configuring-SAML2-DynamicMetadata-Redis.html). | | JPA | [See this guide](Configuring-SAML2-DynamicMetadata-JPA.html). | -| ~~CouchDb~~ | [See this guide](Configuring-SAML2-DynamicMetadata-CouchDb.html). | | Groovy | [See this guide](Configuring-SAML2-DynamicMetadata-Groovy.html). | | Amazon S3 | [See this guide](Configuring-SAML2-DynamicMetadata-AmazonS3.html). | diff --git a/docs/cas-server-documentation/installation/Ticket-Registry-Replication-Encryption.md b/docs/cas-server-documentation/installation/Ticket-Registry-Replication-Encryption.md index 1c574f068772..cc59d0d0e889 100644 --- a/docs/cas-server-documentation/installation/Ticket-Registry-Replication-Encryption.md +++ b/docs/cas-server-documentation/installation/Ticket-Registry-Replication-Encryption.md @@ -13,7 +13,6 @@ by encrypting and signing tickets: * [Hazelcast](../ticketing/Hazelcast-Ticket-Registry.html) * [Ignite](../ticketing/Ignite-Ticket-Registry.html) -* [~~CouchDb~~](../ticketing/CouchDb-Ticket-Registry.html) * [Memcached](../ticketing/Memcached-Ticket-Registry.html) * [Redis](../ticketing/Redis-Ticket-Registry.html) * [MongoDb](../ticketing/MongoDb-Ticket-Registry.html) diff --git a/docs/cas-server-documentation/integration/Attribute-Release-Consent-Storage-CouchDb.md b/docs/cas-server-documentation/integration/Attribute-Release-Consent-Storage-CouchDb.md deleted file mode 100644 index 297ae9ff2e41..000000000000 --- a/docs/cas-server-documentation/integration/Attribute-Release-Consent-Storage-CouchDb.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: default -title: CAS - Attribute Release Consent -category: Attributes ---- - -{% include variables.html %} - -# CouchDb - Attribute Consent Storage - -Support is enabled by including the following module in the WAR Overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-consent-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -## Configuration - -{% include_cached casproperties.html properties="cas.consent.couch-db" %} diff --git a/docs/cas-server-documentation/integration/Attribute-Release-Consent.md b/docs/cas-server-documentation/integration/Attribute-Release-Consent.md index d54c64b0eeca..a01b78597269 100644 --- a/docs/cas-server-documentation/integration/Attribute-Release-Consent.md +++ b/docs/cas-server-documentation/integration/Attribute-Release-Consent.md @@ -83,7 +83,6 @@ User consent decisions may be stored and remembered using one of the following o | Storage | Description | |-------------|--------------------------------------------------------------------| -| ~~CouchDb~~ | [See this guide](Attribute-Release-Consent-Storage-CouchDb.html). | | DynamoDb | [See this guide](Attribute-Release-Consent-Storage-DynamoDb.html). | | Groovy | [See this guide](Attribute-Release-Consent-Storage-Groovy.html). | | JDBC | [See this guide](Attribute-Release-Consent-Storage-JDBC.html). | diff --git a/docs/cas-server-documentation/integration/Attribute-Resolution-Couchbase.md b/docs/cas-server-documentation/integration/Attribute-Resolution-Couchbase.md deleted file mode 100644 index a180b6dd59ab..000000000000 --- a/docs/cas-server-documentation/integration/Attribute-Resolution-Couchbase.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: default -title: CAS - Attribute Resolution -category: Attributes ---- - -{% include variables.html %} - -# Couchbase Attribute Resolution - -The following configuration describes how to fetch and retrieve attributes from Couchbase attribute repositories. - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-couchbase-authentication" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.attribute-repository.couchbase" %} - diff --git a/docs/cas-server-documentation/integration/Attribute-Resolution.md b/docs/cas-server-documentation/integration/Attribute-Resolution.md index 3fd0f9005187..603284e58cf8 100644 --- a/docs/cas-server-documentation/integration/Attribute-Resolution.md +++ b/docs/cas-server-documentation/integration/Attribute-Resolution.md @@ -132,7 +132,6 @@ The following options may be used to fetch attributes in CAS. | Groovy | [See this guide](Attribute-Resolution-Groovy.html). | | REST | [See this guide](Attribute-Resolution-REST.html). | | Grouper | [See this guide](Attribute-Resolution-Grouper.html). | -| ~~Couchbase~~ | [See this guide](Attribute-Resolution-Couchbase.html). | | Redis | [See this guide](Attribute-Resolution-Redis.html). | | JDBC | [See this guide](Attribute-Resolution-JDBC.html). | | OKTA | [See this guide](Attribute-Resolution-Okta.html). | diff --git a/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md b/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md index 0b956dacc897..59a081317e03 100644 --- a/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md +++ b/docs/cas-server-documentation/integration/Configuring-SAML-SP-Integrations.md @@ -143,7 +143,7 @@ The following SAML SP integrations, as samples, are provided by CAS: - + @@ -152,7 +152,7 @@ The following SAML SP integrations, as samples, are provided by CAS: - + diff --git a/docs/cas-server-documentation/logging/Logging.md b/docs/cas-server-documentation/logging/Logging.md index b6fe11ee0c55..446689b8d6f9 100644 --- a/docs/cas-server-documentation/logging/Logging.md +++ b/docs/cas-server-documentation/logging/Logging.md @@ -112,7 +112,7 @@ The following `Appender` elements are only a partial collection of available opt | `JPAAppender` | Writes log events to a relational database table using the Java Persistence API `2.1`. | | `HttpAppender` | Sends log events over HTTP. A Layout must be provided to format the log event. | | `KafkaAppender` | Logs events to an Apache Kafka topic. Each log event is sent as a Kafka record. | -| `NoSQLAppender` | Writes log events to a NoSQL database; Provider implementations currently exist for MongoDB and Apache CouchDB. | +| `NoSQLAppender` | Writes log events to a NoSQL database; Provider implementations exist for MongoDB and Apache CouchDB. | | `RoutingAppender` | Evaluates log events and then routes them to a subordinate `Appender`. | | `SMTPAppender` | Sends an e-mail when a specific logging event occurs, typically on errors or fatal errors. | | `JeroMQ` | The ZeroMQ appender uses the JeroMQ library to send log events to one or more ZeroMQ endpoints. | diff --git a/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication-CouchDb.md b/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication-CouchDb.md deleted file mode 100644 index e9692f1c10a0..000000000000 --- a/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication-CouchDb.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: default -title: CAS - U2F - FIDO Universal 2nd Factor Authentication -category: Multifactor Authentication ---- - -{% include variables.html %} - -# CouchDb U2F - FIDO Universal Registration - -Device registrations may be kept inside a CouchDb instance by including the following module in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-u2f-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.mfa.u2f.couch-db" %} diff --git a/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication.md b/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication.md index 32f496bb6775..a9f53963f47f 100644 --- a/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication.md +++ b/docs/cas-server-documentation/mfa/FIDO-U2F-Authentication.md @@ -62,5 +62,4 @@ The following options are available to store registration records: | MongoDb | Please [see this guide](FIDO-U2F-Authentication-MongoDb.html). | | DynamoDb | Please [see this guide](FIDO-U2F-Authentication-DynamoDb.html). | | Redis | Please [see this guide](FIDO-U2F-Authentication-Redis.html). | -| ~~CouchDb~~ | Please [see this guide](FIDO-U2F-Authentication-CouchDb.html). | | REST | Please [see this guide](FIDO-U2F-Authentication-Rest.html). | diff --git a/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication-Registration-CouchDb.md b/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication-Registration-CouchDb.md deleted file mode 100644 index 39d542ffcd7c..000000000000 --- a/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication-Registration-CouchDb.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: default -title: CAS - Google Authenticator Authentication -category: Multifactor Authentication ---- - -{% include variables.html %} - -# CouchDb Google Authenticator Registration - -Registration records and tokens may be kept inside a CouchDb instance, via the following module: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-gauth-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.mfa.gauth.couch-db" %} - diff --git a/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication.md b/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication.md index f7ac734a1413..f71a61900333 100644 --- a/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication.md +++ b/docs/cas-server-documentation/mfa/GoogleAuthenticator-Authentication.md @@ -67,7 +67,6 @@ records can be controlled via CAS settings. | Storage | Description | |-------------|----------------------------------------------------------------------------------| | JPA | [See this guide](GoogleAuthenticator-Authentication-Registration-JPA.html). | -| ~~CouchDb~~ | [See this guide](GoogleAuthenticator-Authentication-Registration-CouchDb.html). | | MongoDb | [See this guide](GoogleAuthenticator-Authentication-Registration-MongoDb.html). | | DynamoDb | [See this guide](GoogleAuthenticator-Authentication-Registration-DynamoDb.html). | | Redis | [See this guide](GoogleAuthenticator-Authentication-Registration-Redis.html). | diff --git a/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication-Storage-CouchDb.md b/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication-Storage-CouchDb.md deleted file mode 100644 index 38fa37454588..000000000000 --- a/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication-Storage-CouchDb.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: default -title: CAS - Trusted Device Multifactor Authentication -category: Multifactor Authentication ---- - -{% include variables.html %} - -# CouchDb Device Storage - Multifactor Authentication Trusted Device/Browser - -User decisions may also be kept inside a CouchDb instance. - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -Support is provided via the following module: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-trusted-mfa-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.mfa.trusted.couch-db" %} diff --git a/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication.md b/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication.md index 0f260fe0a988..16fa6b9a4c0f 100644 --- a/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication.md +++ b/docs/cas-server-documentation/mfa/Multifactor-TrustedDevice-Authentication.md @@ -83,7 +83,6 @@ Device registrations can also be managed using any one of the following strategi |-------------|-----------------------------------------------------------------------------------| | JSON | [See this guide](Multifactor-TrustedDevice-Authentication-Storage-JSON.html). | | JDBC | [See this guide](Multifactor-TrustedDevice-Authentication-Storage-JDBC.html). | -| ~~CouchDb~~ | [See this guide](Multifactor-TrustedDevice-Authentication-Storage-CouchDb.html). | | MongoDb | [See this guide](Multifactor-TrustedDevice-Authentication-Storage-MongoDb.html). | | DynamoDb | [See this guide](Multifactor-TrustedDevice-Authentication-Storage-DynamoDb.html). | | Redis | [See this guide](Multifactor-TrustedDevice-Authentication-Storage-Redis.html). | diff --git a/docs/cas-server-documentation/mfa/YubiKey-Authentication-Registration-CouchDb.md b/docs/cas-server-documentation/mfa/YubiKey-Authentication-Registration-CouchDb.md deleted file mode 100644 index f1df13994f26..000000000000 --- a/docs/cas-server-documentation/mfa/YubiKey-Authentication-Registration-CouchDb.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: default -title: CAS - YubiKey Authentication -category: Multifactor Authentication ---- - -{% include variables.html %} - -# CouchDb YubiKey Registration - -Support is enabled by including the following dependencies in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-yubikey-couchdb" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -{% include_cached casproperties.html properties="cas.authn.mfa.yubikey.couch-db" %} - -The registration records are kept inside a single CouchDb database of your choosing that will be auto-created by CAS. -The structure of this database's documents is as follows: - -| Field | Description | -|------------|------------------------------------------------------------------| -| `id` | Unique record identifier, acting as the primary key. | -| `publicId` | The public identifier/key of the device used for authentication. | -| `username` | The username whose device is registered. | diff --git a/docs/cas-server-documentation/mfa/YubiKey-Authentication.md b/docs/cas-server-documentation/mfa/YubiKey-Authentication.md index 08b233aab456..b463966c17a3 100644 --- a/docs/cas-server-documentation/mfa/YubiKey-Authentication.md +++ b/docs/cas-server-documentation/mfa/YubiKey-Authentication.md @@ -45,7 +45,6 @@ in order to allow for a successful authentication event. | REST | [See this guide](YubiKey-Authentication-Registration-Rest.html). | | Permissive | [See this guide](YubiKey-Authentication-Registration-Permissive.html). | | JPA | [See this guide](YubiKey-Authentication-Registration-JPA.html). | -| ~~CouchDb~~ | [See this guide](YubiKey-Authentication-Registration-CouchDb.html). | | Redis | [See this guide](YubiKey-Authentication-Registration-Redis.html). | | DynamoDb | [See this guide](YubiKey-Authentication-Registration-DynamoDb.html). | | MongoDb | [See this guide](YubiKey-Authentication-Registration-MongoDb.html). | diff --git a/docs/cas-server-documentation/release_notes/RC6.md b/docs/cas-server-documentation/release_notes/RC6.md index f80a607b7573..529d54067646 100644 --- a/docs/cas-server-documentation/release_notes/RC6.md +++ b/docs/cas-server-documentation/release_notes/RC6.md @@ -50,6 +50,12 @@ A new ticket registry implementation backed by [Google Cloud's PubSub](../ticket Supported grant types and response types are recognized during [OpenID Connect Dynamic Registration](../authentication/OIDC-Authentication-Dynamic-Registration.html). Furthermore, sensible defaults would be used if grant types or response types are not explicitly requested. +### Feature Removals + +Modules, features and plugins that support functionality for Apache CouchDb or Couchbase are now removed. +If you are currently using any of these plugins or features, we recommend that you consider a +better alternative or prepare to adopt and maintain the feature on your own. + ## Other Stuff - Ticket registry operations are now *observed* using [Micrometer Observations](https://micrometer.io) and then reported as metrics. diff --git a/docs/cas-server-documentation/services/CouchDb-Service-Management.md b/docs/cas-server-documentation/services/CouchDb-Service-Management.md deleted file mode 100644 index 2a90f5867f8a..000000000000 --- a/docs/cas-server-documentation/services/CouchDb-Service-Management.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -layout: default -title: CAS - CouchDB Service Registry -category: Services ---- - -{% include variables.html %} - -# CouchDB Service Registry - -CouchDB integration is enabled by including the following dependency in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-couchdb-service-registry" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -[CouchDB](https://couchdb.apache.org/) is a highly available, open source NoSQL database server based on -[Erlang/OTP](https://www.erlang.org) and its mnesia database. The intention of this registry is to leverage the capability of CouchDB -server to provide high availability to CAS across multiple data centers. - -## Configuration - -{% include_cached casproperties.html properties="cas.service-registry.couch-db" %} - -## Auto Initialization - -Upon startup and configuration permitting, the registry is able to auto initialize itself from default JSON service definitions available to CAS. See [this guide](AutoInitialization-Service-Management.html) for more info. - -## Troubleshooting - -To enable additional logging, configure the log4j configuration file to add the following -levels: - -```xml -... - - - - -... -``` diff --git a/docs/cas-server-documentation/services/Couchbase-Service-Management.md b/docs/cas-server-documentation/services/Couchbase-Service-Management.md deleted file mode 100644 index 35b589c417f5..000000000000 --- a/docs/cas-server-documentation/services/Couchbase-Service-Management.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -layout: default -title: CAS - Couchbase Service Registry -category: Services ---- - -{% include variables.html %} - -# Couchbase Service Registry - -Couchbase integration is enabled by including the following dependency in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-couchbase-service-registry" %} - -[Couchbase](https://www.couchbase.com) is a highly available, open source NoSQL database server based on -[Erlang/OTP](https://www.erlang.org) and its mnesia database. The intention of this registry is to leverage the capability of Couchbase server to provide high availability to CAS. - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -## Configuration - -{% include_cached casproperties.html properties="cas.service-registry.couchbase" %} - -The Couchbase integration currently assumes that the service registries are stored -in their own buckets. Optionally set passwords for the buckets, optionally setup -redundancy and replication as per normal Couchbase configuration. - -The only truly mandatory setting is the list of nodes. -The other settings are optional, but this is designed to store data in buckets -so in reality the bucket property must also be set. - -## Auto Initialization - -Upon startup and configuration permitting, the registry is able to auto initialize itself from default JSON service definitions available to CAS. See [this guide](AutoInitialization-Service-Management.html) for more info. - - -## Troubleshooting - -To enable additional logging, configure the log4j configuration file to add the following -levels: - -```xml -... - - - - -... -``` diff --git a/docs/cas-server-documentation/services/Service-Management.md b/docs/cas-server-documentation/services/Service-Management.md index 64a6ee29aaa0..44a297f92c6c 100644 --- a/docs/cas-server-documentation/services/Service-Management.md +++ b/docs/cas-server-documentation/services/Service-Management.md @@ -78,8 +78,6 @@ The following options may be used to store services in CAS. | Redis | [See this guide](Redis-Service-Management.html). | Store service definitions in Redis. Candidate for HA deployments. | | LDAP | [See this guide](LDAP-Service-Management.html). | Store service definitions in a directory server. Candidate for HA deployments. | | JPA | [See this guide](JPA-Service-Management.html). | Store service definitions in a relational database (Oracle, MySQL, etc). Candidate for HA deployments. | -| ~~Couchbase~~ | [See this guide](Couchbase-Service-Management.html). | Store service definitions in Couchbase. Candidate for HA deployments. | -| ~~CouchDB~~ | [See this guide](CouchDb-Service-Management.html). | Store service definitions in CouchDb. Candidate for HA deployments. | | DynamoDb | [See this guide](DynamoDb-Service-Management.html). | Store service definitions in DynamoDb. Candidate for HA deployments. | | Amazon S3 | [See this guide](AmazonS3-Service-Management.html). | Store service definitions in Amazon S3 buckets. Candidate for HA deployments. | | CosmosDb | [See this guide](CosmosDb-Service-Management.html). | Store service definitions in an Azure CosmosDb. Candidate for HA deployments. | diff --git a/docs/cas-server-documentation/sidebar.md b/docs/cas-server-documentation/sidebar.md index 3e2399b5753e..fe454d184b6c 100644 --- a/docs/cas-server-documentation/sidebar.md +++ b/docs/cas-server-documentation/sidebar.md @@ -107,7 +107,6 @@ layout: null * [REST](/cas/{{ version }}/authentication/Rest-Authentication.html) * [AWS Cloud Directory](/cas/{{ version }}/authentication/AWS-CloudDirectory-Authentication.html) * [AWS Cognito](/cas/{{ version }}/authentication/AWS-Cognito-Authentication.html) - * [~~Couchbase~~](/cas/{{ version }}/authentication/Couchbase-Authentication.html) * [Basic](/cas/{{ version }}/authentication/Basic-Authentication.html) * [Groovy](/cas/{{ version }}/authentication/Groovy-Authentication.html) * [QR Code](/cas/{{ version }}/authentication/QRCode-Authentication.html) @@ -122,7 +121,6 @@ layout: null * [Custom](/cas/{{ version }}/authentication/Configuring-Custom-Authentication.html) * [Throttling](#authnthrottling) * [Overview](/cas/{{ version }}/authentication/Configuring-Authentication-Throttling.html) - * [~~CouchDb~~](/cas/{{ version }}/authentication/Configuring-Authentication-Throttling-CouchDb.html) * [Hazelcast](/cas/{{ version }}/authentication/Configuring-Authentication-Throttling-Hazelcast.html) * [JDBC](/cas/{{ version }}/authentication/Configuring-Authentication-Throttling-JDBC.html) * [MongoDb](/cas/{{ version }}/authentication/Configuring-Authentication-Throttling-MongoDb.html) @@ -132,7 +130,6 @@ layout: null * [Proxying](/cas/{{ version }}/authentication/Configuring-Proxy-Authentication.html) * [Events](#authnevents) * [Overview](/cas/{{ version }}/authentication/Configuring-Authentication-Events.html) - * [~~CouchDb~~](/cas/{{ version }}/authentication/Configuring-Authentication-Events-CouchDb.html) * [DynamoDb](/cas/{{ version }}/authentication/Configuring-Authentication-Events-DynamoDb.html) * [InfluxDb](/cas/{{ version }}/authentication/Configuring-Authentication-Events-InfluxDb.html) * [JPA/JDBC](/cas/{{ version }}/authentication/Configuring-Authentication-Events-JPA.html) @@ -205,7 +202,6 @@ layout: null * [JSON](/cas/{{ version }}/integration/Attribute-Resolution-JSON.html) * [REST](/cas/{{ version }}/integration/Attribute-Resolution-REST.html) * [Grouper](/cas/{{ version }}/integration/Attribute-Resolution-Grouper.html) - * [~~Couchbase~~](/cas/{{ version }}/integration/Attribute-Resolution-Couchbase.html) * [Redis](/cas/{{ version }}/integration/Attribute-Resolution-Redis.html) * [Okta](/cas/{{ version }}/integration/Attribute-Resolution-Okta.html) * [Apache Syncope](/cas/{{ version }}/integration/Attribute-Resolution-Syncope.html) @@ -242,7 +238,6 @@ layout: null * [Overview](/cas/{{ version }}/integration/Attribute-Release-Consent.html) * [Activation](/cas/{{ version }}/integration/Attribute-Release-Consent-Activation.html) * [Storage](#attrconsentstorage) - * [~~CouchDb~~](/cas/{{ version }}/integration/Attribute-Release-Consent-Storage-CouchDb.html) * [Custom](/cas/{{ version }}/integration/Attribute-Release-Consent-Storage-Custom.html) * [Groovy](/cas/{{ version }}/integration/Attribute-Release-Consent-Storage-Groovy.html) * [JDBC](/cas/{{ version }}/integration/Attribute-Release-Consent-Storage-JDBC.html) @@ -260,7 +255,6 @@ layout: null * [Duo Security](/cas/{{ version }}/mfa/DuoSecurity-Authentication.html) * [YubiKey](#mfayubikey) * [Overview](/cas/{{ version }}/mfa/YubiKey-Authentication.html) - * [~~CouchDb~~](/cas/{{ version }}/mfa/YubiKey-Authentication-Registration-CouchDb.html) * [Custom](/cas/{{ version }}/mfa/YubiKey-Authentication-Registration-Custom.html) * [DynamoDb](/cas/{{ version }}/mfa/YubiKey-Authentication-Registration-DynamoDb.html) * [JPA](/cas/{{ version }}/mfa/YubiKey-Authentication-Registration-JPA.html) @@ -272,7 +266,6 @@ layout: null * [RSA/Radius](/cas/{{ version }}/mfa/RADIUS-Authentication.html) * [Google Authenticator](#mfagoogleauthn) * [Overview](/cas/{{ version }}/mfa/GoogleAuthenticator-Authentication.html) - * [~~CouchDb~~](/cas/{{ version }}/mfa/GoogleAuthenticator-Authentication-Registration-CouchDb.html) * [JPA](/cas/{{ version }}/mfa/GoogleAuthenticator-Authentication-Registration-JPA.html) * [JSON](/cas/{{ version }}/mfa/GoogleAuthenticator-Authentication-Registration-JSON.html) * [LDAP](/cas/{{ version }}/mfa/GoogleAuthenticator-Authentication-Registration-LDAP.html) @@ -288,7 +281,6 @@ layout: null * [Token Management](/cas/{{ version }}/mfa/Simple-Multifactor-Authentication-TokenManagement.html) * [FIDO U2F](#mfafidou2f) * [Overview](/cas/{{ version }}/mfa/FIDO-U2F-Authentication.html) - * [~~CouchDb~~](/cas/{{ version }}/mfa/FIDO-U2F-Authentication-CouchDb.html) * [DynamoDb](/cas/{{ version }}/mfa/FIDO-U2F-Authentication-DynamoDb.html) * [Groovy](/cas/{{ version }}/mfa/FIDO-U2F-Authentication-Groovy.html) * [JPA](/cas/{{ version }}/mfa/FIDO-U2F-Authentication-JPA.html) @@ -330,7 +322,6 @@ layout: null * [Bypass](/cas/{{ version }}/mfa/Multifactor-TrustedDevice-Authentication-Bypass.html) * [Device Fingerprint](/cas/{{ version }}/mfa/Multifactor-TrustedDevice-Authentication-DeviceFingerprint.html) * [Storage](#mfatrusteddevicesstorage) - * [~~CouchDb~~](/cas/{{ version }}/mfa/Multifactor-TrustedDevice-Authentication-Storage-CouchDb.html) * [DynamoDb](/cas/{{ version }}/mfa/Multifactor-TrustedDevice-Authentication-Storage-DynamoDb.html) * [JDBC](/cas/{{ version }}/mfa/Multifactor-TrustedDevice-Authentication-Storage-JDBC.html) * [JSON](/cas/{{ version }}/mfa/Multifactor-TrustedDevice-Authentication-Storage-JSON.html) @@ -396,7 +387,6 @@ layout: null * [JPA](/cas/{{ version }}/ticketing/JPA-Ticket-Registry.html) * [Ignite](/cas/{{ version }}/ticketing/Ignite-Ticket-Registry.html) * [CosmosDb](/cas/{{ version }}/ticketing/CosmosDb-Ticket-Registry.html) - * [~~CouchDb~~](/cas/{{ version }}/ticketing/CouchDb-Ticket-Registry.html) * [Redis](/cas/{{ version }}/ticketing/Redis-Ticket-Registry.html) * [Cassandra](/cas/{{ version }}/ticketing/Cassandra-Ticket-Registry.html) * [MongoDb](/cas/{{ version }}/ticketing/MongoDb-Ticket-Registry.html) @@ -449,8 +439,6 @@ layout: null * [Amazon S3](/cas/{{ version }}/services/AmazonS3-Service-Management.html) * [Cassandra](/cas/{{ version }}/services/Cassandra-Service-Management.html) * [CosmosDb](/cas/{{ version }}/services/CosmosDb-Service-Management.html) - * [~~Couchbase~~](/cas/{{ version }}/services/Couchbase-Service-Management.html) - * [~~CouchDb~~](/cas/{{ version }}/services/CouchDb-Service-Management.html) * [REST](/cas/{{ version }}/services/REST-Service-Management.html) * [Custom](/cas/{{ version }}/services/Custom-Service-Management.html) @@ -546,7 +534,6 @@ layout: null * [REST](/cas/{{ version }}/authentication/Surrogate-Authentication-Storage-REST.html) * [Groovy](/cas/{{ version }}/authentication/Surrogate-Authentication-Storage-Groovy.html) * [JDBC](/cas/{{ version }}/authentication/Surrogate-Authentication-Storage-JDBC.html) - * [~~CouchDb~~](/cas/{{ version }}/authentication/Surrogate-Authentication-Storage-CouchDb.html) * [Custom](/cas/{{ version }}/authentication/Surrogate-Authentication-Storage-Custom.html) * [Account Registration](#acctregistration) * [Overview](/cas/{{ version }}/registration/Account-Registration-Overview.html) @@ -575,8 +562,6 @@ layout: null * [Audits](#auditsoverview) * [Overview](/cas/{{ version }}/audits/Audits.html) * [File](/cas/{{ version }}/audits/Audits-File.html) - * [~~Couchbase~~](/cas/{{ version }}/audits/Audits-Couchbase.html) - * [CouchDb](/cas/{{ version }}/audits/Audits-CouchDb.html) * [JDBC](/cas/{{ version }}/audits/Audits-Database.html) * [DynamoDb](/cas/{{ version }}/audits/Audits-DynamoDb.html) * [MongoDb](/cas/{{ version }}/audits/Audits-MongoDb.html) @@ -624,8 +609,6 @@ layout: null * [LDAP](/cas/{{ version }}/webflow/Webflow-Customization-AUP-LDAP.html) * [MongoDb](/cas/{{ version }}/webflow/Webflow-Customization-AUP-MongoDb.html) * [Redis](/cas/{{ version }}/webflow/Webflow-Customization-AUP-Redis.html) - * [CouchDb](/cas/{{ version }}/webflow/Webflow-Customization-AUP-CouchDb.html) - * [~~Couchbase~~](/cas/{{ version }}/webflow/Webflow-Customization-AUP-Couchbase.html) * [JDBC](/cas/{{ version }}/webflow/Webflow-Customization-AUP-JDBC.html) * [REST](/cas/{{ version }}/webflow/Webflow-Customization-AUP-REST.html) * [Custom](/cas/{{ version }}/webflow/Webflow-Customization-AUP-Custom.html) diff --git a/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md b/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md index 38028ef73cab..a5f278ed5202 100644 --- a/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md +++ b/docs/cas-server-documentation/ticketing/Configuring-Ticketing-Components.md @@ -59,7 +59,6 @@ CAS also provides support for a variety of other databases, including Redis, Mon Cassandra, for ticket storage and persistence: * [Redis](Redis-Ticket-Registry.html) -* [~~CouchDb~~](CouchDb-Ticket-Registry.html) * [MongoDb](MongoDb-Ticket-Registry.html) * [DynamoDb](DynamoDb-Ticket-Registry.html) diff --git a/docs/cas-server-documentation/ticketing/CouchDb-Ticket-Registry.md b/docs/cas-server-documentation/ticketing/CouchDb-Ticket-Registry.md deleted file mode 100644 index b6fce8e29709..000000000000 --- a/docs/cas-server-documentation/ticketing/CouchDb-Ticket-Registry.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -layout: default -title: CAS - CouchDB Ticket Registry -category: Ticketing ---- - -{% include variables.html %} - -# CouchDB Ticket Registry - -CouchDB integration is enabled by including the following dependency in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-couchdb-ticket-registry" %} - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -[CouchDB](https://couchdb.apache.org) is a highly available, open source NoSQL database server based on -[Erlang/OTP](https://www.erlang.org) and its mnesia database. The intention of this -registry is to leverage the multi-master, multi-datacenter capabilities of CouchDB server to provide high availability to CAS. - -## Configuration - -{% include_cached casproperties.html properties="cas.ticket.registry.couch-db" %} - - -The only truly mandatory setting is the URL. However, CouchDB should not be used in admin party mode in production, so username and password are needed as well. - -## Caveat - -The trade off for multi-master replication across multiple datacenters is CouchDB does not fully delete -records. Depending on deployment scale, usage, and available storage, the database may need regular cleaning -through normal CouchDB techniques. - -## Troubleshooting - -To enable additional logging, configure the log4j configuration file to add the following -levels: - -```xml -... - - - - -... -``` diff --git a/docs/cas-server-documentation/webflow/Webflow-Customization-AUP-CouchDb.md b/docs/cas-server-documentation/webflow/Webflow-Customization-AUP-CouchDb.md deleted file mode 100644 index e2da5705153e..000000000000 --- a/docs/cas-server-documentation/webflow/Webflow-Customization-AUP-CouchDb.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: default -title: CAS - Web Flow Acceptable Usage Policy -category: Acceptable Usage Policy ---- - -{% include variables.html %} - -# CouchDb Acceptable Usage Policy - -CAS can be configured to use a CouchDb instance as the storage mechanism. Upon accepting the -policy, the adopter is expected to provide a collection name where the decision is kept and -the document is assumed to contain a `username` column as well as one that matches the AUP attribute name defined. - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -Support is enabled by including the following dependency in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-aup-couchdb" %} - -{% include_cached casproperties.html properties="cas.acceptable-usage-policy.couch-db" %} diff --git a/docs/cas-server-documentation/webflow/Webflow-Customization-AUP-Couchbase.md b/docs/cas-server-documentation/webflow/Webflow-Customization-AUP-Couchbase.md deleted file mode 100644 index 0735cbad56a4..000000000000 --- a/docs/cas-server-documentation/webflow/Webflow-Customization-AUP-Couchbase.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: default -title: CAS - Web Flow Acceptable Usage Policy -category: Acceptable Usage Policy ---- - -{% include variables.html %} - -# Couchbase Acceptable Usage Policy - -CAS can be configured to use a Couchbase instance as the storage mechanism. Upon accepting the policy, the -decision is kept inside a document with a `username` column and the AUP attribute name with the result of the decision. - -
:warning: Usage -

This feature is deprecated and is scheduled to be removed in the future.

-
- -Support is enabled by including the following dependency in the WAR overlay: - -{% include_cached casmodule.html group="org.apereo.cas" module="cas-server-support-aup-couchbase" %} - -{% include_cached casproperties.html properties="cas.acceptable-usage-policy.couchbase" %} diff --git a/docs/cas-server-documentation/webflow/Webflow-Customization-AUP.md b/docs/cas-server-documentation/webflow/Webflow-Customization-AUP.md index 696d444fa048..2482982d4e80 100644 --- a/docs/cas-server-documentation/webflow/Webflow-Customization-AUP.md +++ b/docs/cas-server-documentation/webflow/Webflow-Customization-AUP.md @@ -75,8 +75,6 @@ ask for policy acceptance. Upon accepting the policy, the result will be stored | LDAP | [See this guide](Webflow-Customization-AUP-LDAP.html). | | MongoDb | [See this guide](Webflow-Customization-AUP-MongoDb.html). | | Redis | [See this guide](Webflow-Customization-AUP-Redis.html). | -| ~~CouchDb~~ | [See this guide](Webflow-Customization-AUP-CouchDb.html). | -| ~~Couchbase~~ | [See this guide](Webflow-Customization-AUP-Couchbase.html). | | JDBC | [See this guide](Webflow-Customization-AUP-JDBC.html). | | REST | [See this guide](Webflow-Customization-AUP-REST.html). | | Custom | [See this guide](Webflow-Customization-AUP-Custom.html). | diff --git a/gradle.properties b/gradle.properties index 44aaa473ab52..434f33a4bb1d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -396,10 +396,6 @@ jakartaMailVersion=2.0.1 sendGridVersion=4.9.3 jakartaActivationVersion=2.1.1 ############################### -# Couchbase Versions -############################### -couchbaseVersion=3.4.4 -############################### # GeoCoding & Maps Versions ############################### ipGeoLocationVersion=1.0.13 @@ -414,10 +410,6 @@ gsonVersion=2.10.1 googleCloudSdkVersion=4.1.2 googleCloudMonitorVersion=3.14.0 ############################### -# CouchDb Versions -############################### -ektorpVersion=1.5.0 -############################### # Web JARs ############################### webjarLocatorVersion=0.52 diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index c3c290bb5372..6263f1956444 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -45,6 +45,22 @@ ext.libraries = [ exclude(group: "ch.qos.logback", module: "logback-classic") } ], + googlecloudfirestore : [ + dependencies.create("com.google.cloud:spring-cloud-gcp-starter-data-firestore:$googleCloudSdkVersion") { + exclude(group: "org.slf4j", module: "slf4j-api") + exclude(group: "com.google.guava", module: "guava") + exclude(group: "commons-codec", module: "commons-codec") + exclude(group: "ch.qos.logback", module: "logback-core") + exclude(group: "ch.qos.logback", module: "logback-classic") + }, + dependencies.create("com.google.cloud:spring-cloud-gcp-data-firestore:$googleCloudSdkVersion") { + exclude(group: "org.slf4j", module: "slf4j-api") + exclude(group: "com.google.guava", module: "guava") + exclude(group: "commons-codec", module: "commons-codec") + exclude(group: "ch.qos.logback", module: "logback-core") + exclude(group: "ch.qos.logback", module: "logback-classic") + } + ], firebaseadmin : [ dependencies.create("com.google.api-client:google-api-client:$googleApiClientVersion") { exclude(group: "org.slf4j", module: "slf4j-api") @@ -1091,8 +1107,6 @@ ext.libraries = [ exclude(group: "com.fasterxml.jackson", module: "jackson-bom") } ], - couchbase : dependencies.create("com.couchbase.client:java-client:$couchbaseVersion"), - ektorp : dependencies.create("org.ektorp:org.ektorp:$ektorpVersion"), jcifs : [ dependencies.create("jcifs:jcifs:$jcifsVersion") { exclude(group: "javax.servlet", module: "servlet-api") @@ -2061,14 +2075,6 @@ ext.libraries = [ dependencies.create("com.github.stephenc.jcip:jcip-annotations:1.0-1") { } ], - pac4jcouchdb : [ - dependencies.create("org.pac4j:pac4j-couch:$pac4jVersion") { - exclude(group: "org.pac4j", module: "pac4j-core") - exclude(group: "org.ektorp", module: "org.ektorp") - exclude(group: "com.fasterxml.jackson.core", module: "jackson-databind") - exclude(group: "com.fasterxml.jackson.core", module: "jackson-annotations") - } - ], persondirectory : dependencies.create("org.apereo.service.persondir:person-directory-impl:$personDirectoryVersion") { exclude(group: "commons-logging", module: "commons-logging") exclude(group: "org.slf4j", module: "slf4j-api") diff --git a/gradle/maven.gradle b/gradle/maven.gradle index fcefb7926b76..b71591536eb1 100644 --- a/gradle/maven.gradle +++ b/gradle/maven.gradle @@ -179,12 +179,6 @@ ext.createPomRepositories = { node -> repository.appendNode("releases").appendNode("enabled", "true") repository.appendNode("snapshots").appendNode("enabled", "false") - repository = repositories.appendNode("repository") - repository.appendNode("id", "couchbase") - repository.appendNode("url", "https://files.couchbase.com/maven2/") - repository.appendNode("releases").appendNode("enabled", "true") - repository.appendNode("snapshots").appendNode("enabled", "false") - repository = repositories.appendNode("repository") repository.appendNode("id", "sonatype-snapshot") repository.appendNode("url", "https://oss.sonatype.org/content/repositories/snapshots") diff --git a/gradle/overrides.gradle b/gradle/overrides.gradle index 4e0a5641a973..b01b737161cf 100644 --- a/gradle/overrides.gradle +++ b/gradle/overrides.gradle @@ -99,9 +99,6 @@ configurations.all { if (requested.group == "net.sourceforge.jtds") { details.useVersion("${jtdsVersion}") } - if (requested.group == "com.couchbase.client" && requested.name == "java-client") { - details.useVersion("${couchbaseVersion}") - } if (requested.group == "com.github.ben-manes.caffeine") { details.useVersion("${caffeineVersion}") } diff --git a/gradle/tests.gradle b/gradle/tests.gradle index c623f4fe9ac8..77a3420943db 100644 --- a/gradle/tests.gradle +++ b/gradle/tests.gradle @@ -19,8 +19,6 @@ enum TestCategories { Cipher, Consent, Cookie, - Couchbase, - CouchDb, Delegation, DuoSecurity, DynamoDb, diff --git a/settings.gradle b/settings.gradle index f9a3f203f4f0..9eeb9064981a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -164,16 +164,12 @@ include "support:cas-server-support-account-mgmt" include "support:cas-server-support-acme" include "support:cas-server-support-actions-core" include "support:cas-server-support-actions" -include "support:cas-server-support-audit-couchbase" -include "support:cas-server-support-audit-couchdb" include "support:cas-server-support-audit-dynamodb" include "support:cas-server-support-audit-jdbc" include "support:cas-server-support-audit-mongo" include "support:cas-server-support-audit-redis" include "support:cas-server-support-audit-rest" include "support:cas-server-support-aup-core" -include "support:cas-server-support-aup-couchbase" -include "support:cas-server-support-aup-couchdb" include "support:cas-server-support-aup-jdbc" include "support:cas-server-support-aup-ldap" include "support:cas-server-support-aup-mongo" @@ -213,7 +209,6 @@ include "support:cas-server-support-configuration-cloud-vault" include "support:cas-server-support-configuration-cloud-zookeeper" include "support:cas-server-support-consent-api" include "support:cas-server-support-consent-core" -include "support:cas-server-support-consent-couchdb" include "support:cas-server-support-consent-dynamodb" include "support:cas-server-support-consent-jdbc" include "support:cas-server-support-consent-ldap" @@ -225,13 +220,6 @@ include "support:cas-server-support-consul-client" include "support:cas-server-support-cosmosdb-core" include "support:cas-server-support-cosmosdb-service-registry" include "support:cas-server-support-cosmosdb-ticket-registry" -include "support:cas-server-support-couchbase-authentication" -include "support:cas-server-support-couchbase-core" -include "support:cas-server-support-couchbase-service-registry" -include "support:cas-server-support-couchdb-authentication" -include "support:cas-server-support-couchdb-core" -include "support:cas-server-support-couchdb-service-registry" -include "support:cas-server-support-couchdb-ticket-registry" include "support:cas-server-support-discovery-profile" include "support:cas-server-support-duo" include "support:cas-server-support-duo-core" @@ -241,7 +229,6 @@ include "support:cas-server-support-dynamodb-service-registry" include "support:cas-server-support-dynamodb-ticket-registry" include "support:cas-server-support-electrofence" include "support:cas-server-support-eureka-client" -include "support:cas-server-support-events-couchdb" include "support:cas-server-support-events-dynamodb" include "support:cas-server-support-events-influxdb" include "support:cas-server-support-events-jpa" @@ -251,7 +238,6 @@ include "support:cas-server-support-events-redis" include "support:cas-server-support-gauth" include "support:cas-server-support-gauth-core" include "support:cas-server-support-gauth-core-mfa" -include "support:cas-server-support-gauth-couchdb" include "support:cas-server-support-gauth-dynamodb" include "support:cas-server-support-gauth-jpa" include "support:cas-server-support-gauth-ldap" @@ -388,7 +374,6 @@ include "support:cas-server-support-saml-idp-core" include "support:cas-server-support-saml-idp-discovery" include "support:cas-server-support-saml-idp-metadata" include "support:cas-server-support-saml-idp-metadata-aws-s3" -include "support:cas-server-support-saml-idp-metadata-couchdb" include "support:cas-server-support-saml-idp-metadata-jpa" include "support:cas-server-support-saml-idp-metadata-git" include "support:cas-server-support-saml-idp-metadata-mongo" @@ -427,7 +412,6 @@ include "support:cas-server-support-spnego-webflow" include "support:cas-server-support-surrogate-api" include "support:cas-server-support-surrogate-core" include "support:cas-server-support-surrogate-authentication" -include "support:cas-server-support-surrogate-authentication-couchdb" include "support:cas-server-support-surrogate-authentication-jdbc" include "support:cas-server-support-surrogate-authentication-ldap" include "support:cas-server-support-surrogate-authentication-rest" @@ -440,7 +424,6 @@ include "support:cas-server-support-themes-core" include "support:cas-server-support-throttle" include "support:cas-server-support-throttle-bucket4j" include "support:cas-server-support-throttle-core" -include "support:cas-server-support-throttle-couchdb" include "support:cas-server-support-throttle-hazelcast" include "support:cas-server-support-throttle-jdbc" include "support:cas-server-support-throttle-ldap" @@ -456,7 +439,6 @@ include "support:cas-server-support-token-webflow" include "support:cas-server-support-trusted" include "support:cas-server-support-trusted-mfa" include "support:cas-server-support-trusted-mfa-core" -include "support:cas-server-support-trusted-mfa-couchdb" include "support:cas-server-support-trusted-mfa-jdbc" include "support:cas-server-support-trusted-mfa-mongo" include "support:cas-server-support-trusted-mfa-redis" @@ -465,7 +447,6 @@ include "support:cas-server-support-trusted-mfa-dynamodb" include "support:cas-server-support-trusted-webflow" include "support:cas-server-support-u2f" include "support:cas-server-support-u2f-core" -include "support:cas-server-support-u2f-couchdb" include "support:cas-server-support-u2f-dynamodb" include "support:cas-server-support-u2f-jpa" include "support:cas-server-support-u2f-mongo" @@ -495,7 +476,6 @@ include "support:cas-server-support-yaml-service-registry" include "support:cas-server-support-yubikey" include "support:cas-server-support-yubikey-core" include "support:cas-server-support-yubikey-core-mfa" -include "support:cas-server-support-yubikey-couchdb" include "support:cas-server-support-yubikey-dynamodb" include "support:cas-server-support-yubikey-jpa" include "support:cas-server-support-yubikey-mongo" diff --git a/support/cas-server-support-audit-couchbase/build.gradle b/support/cas-server-support-audit-couchbase/build.gradle deleted file mode 100644 index 23d2bb391f1b..000000000000 --- a/support/cas-server-support-audit-couchbase/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -description = "Apereo CAS Couchbase Audit Support" -ext { - maxParallelForksForTests = 1 - publishMetadata = true - projectMetadata = [ - category: "Audits", - title: "Audits via Couchbase" - ] -} -dependencies { - api project(":api:cas-server-core-api") - api project(":api:cas-server-core-api-audit") - - api libraries.couchbase - - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-audit-api") - implementation project(":core:cas-server-core-services") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":core:cas-server-core-services-registry") - implementation project(":support:cas-server-support-couchbase-core") - - testImplementation project(":support:cas-server-support-person-directory") - - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-audit") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-web-api") - testImplementation project(":core:cas-server-core-configuration") - - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-audit", configuration: "tests") -} diff --git a/support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/audit/CouchbaseAuditTrailManager.java b/support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/audit/CouchbaseAuditTrailManager.java deleted file mode 100644 index 88629727e9b5..000000000000 --- a/support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/audit/CouchbaseAuditTrailManager.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.apereo.cas.audit; - -import org.apereo.cas.audit.spi.AbstractAuditTrailManager; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.util.DateTimeUtils; -import org.apereo.cas.util.function.FunctionUtils; -import org.apereo.cas.util.serialization.StringSerializer; - -import com.couchbase.client.java.json.JsonObject; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import lombok.val; -import org.apereo.inspektr.audit.AuditActionContext; - -import java.io.StringWriter; -import java.time.LocalDate; -import java.util.Date; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * This is {@link CouchbaseAuditTrailManager}. - * - * @author Misagh Moayyed - * @since 6.0.0 - * @deprecated Since 7.0.0 - */ -@Setter -@RequiredArgsConstructor -@Deprecated(since = "7.0.0") -public class CouchbaseAuditTrailManager extends AbstractAuditTrailManager { - private final CouchbaseClientFactory couchbase; - - private final StringSerializer serializer; - - public CouchbaseAuditTrailManager(final CouchbaseClientFactory couchbase, - final StringSerializer serializer, - final boolean asynchronous) { - this(couchbase, serializer); - this.asynchronous = asynchronous; - } - - @Override - @SuppressWarnings("JavaUtilDate") - public Set getAuditRecords(final Map whereClause) { - val localDate = (LocalDate) whereClause.get(WhereClauseFields.DATE); - val parameters = JsonObject.create().put("whenActionWasPerformed", DateTimeUtils.dateOf(localDate).getTime()); - val queryBuilder = new StringBuilder("whenActionWasPerformed >= $whenActionWasPerformed"); - if (whereClause.containsKey(WhereClauseFields.PRINCIPAL)) { - parameters.put("principal", whereClause.get(WhereClauseFields.PRINCIPAL).toString()); - queryBuilder.append(" and principal = $principal"); - } - val result = couchbase.select(queryBuilder.toString(), Optional.of(parameters)); - - return result.rowsAsObject() - .stream() - .map(row -> { - val json = row.toString(); - val bucket = JsonObject.fromJson(json).getObject(couchbase.getBucket()); - return new AuditActionContext(bucket.getString("principal"), - bucket.getString("resourceOperatedUpon"), - bucket.getString("actionPerformed"), - bucket.getString("applicationCode"), - new Date(bucket.getArray("whenActionWasPerformed").getLong(1)), - bucket.getString("clientIpAddress"), - bucket.getString("serverIpAddress"), - bucket.getString("userAgent")); - }) - .collect(Collectors.toSet()); - } - - @Override - protected void saveAuditRecord(final AuditActionContext audit) { - FunctionUtils.doUnchecked(__ -> { - try (val stringWriter = new StringWriter()) { - this.serializer.to(stringWriter, audit); - this.couchbase.bucketUpsertDefaultCollection(stringWriter.toString()); - } - }); - } -} diff --git a/support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/config/CasSupportCouchbaseAuditConfiguration.java b/support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/config/CasSupportCouchbaseAuditConfiguration.java deleted file mode 100644 index aab4f38dcbe5..000000000000 --- a/support/cas-server-support-audit-couchbase/src/main/java/org/apereo/cas/config/CasSupportCouchbaseAuditConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer; -import org.apereo.cas.audit.CouchbaseAuditTrailManager; -import org.apereo.cas.audit.spi.AuditActionContextJsonSerializer; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.couchbase.core.DefaultCouchbaseClientFactory; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.apereo.inspektr.audit.AuditTrailManager; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CasSupportCouchbaseAuditConfiguration}. - * - * @author Misagh Moayyed - * @since 6.0.0 - * @deprecated Since 7.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Audit, module = "couchbase") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CasSupportCouchbaseAuditConfiguration { - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - @ConditionalOnMissingBean(name = "auditsCouchbaseClientFactory") - public CouchbaseClientFactory auditsCouchbaseClientFactory(final CasConfigurationProperties casProperties) { - val cb = casProperties.getAudit().getCouchbase(); - return new DefaultCouchbaseClientFactory(cb); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "couchbaseAuditTrailManager") - public AuditTrailManager couchbaseAuditTrailManager( - @Qualifier("auditsCouchbaseClientFactory") - final CouchbaseClientFactory auditsCouchbaseClientFactory, - final CasConfigurationProperties casProperties) { - val cb = casProperties.getAudit().getCouchbase(); - return new CouchbaseAuditTrailManager(auditsCouchbaseClientFactory, - new AuditActionContextJsonSerializer(), cb.isAsynchronous()); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "couchbaseAuditTrailExecutionPlanConfigurer") - public AuditTrailExecutionPlanConfigurer couchbaseAuditTrailExecutionPlanConfigurer( - @Qualifier("couchbaseAuditTrailManager") - final AuditTrailManager couchbaseAuditTrailManager) { - return plan -> plan.registerAuditTrailManager(couchbaseAuditTrailManager); - } -} diff --git a/support/cas-server-support-audit-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-audit-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index c2268fac9e0a..000000000000 --- a/support/cas-server-support-audit-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CasSupportCouchbaseAuditConfiguration diff --git a/support/cas-server-support-audit-couchbase/src/test/java/org/apereo/cas/audit/CouchbaseAuditTrailManagerTests.java b/support/cas-server-support-audit-couchbase/src/test/java/org/apereo/cas/audit/CouchbaseAuditTrailManagerTests.java deleted file mode 100644 index 28c9c65ed529..000000000000 --- a/support/cas-server-support-audit-couchbase/src/test/java/org/apereo/cas/audit/CouchbaseAuditTrailManagerTests.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.apereo.cas.audit; - -import org.apereo.cas.audit.spi.BaseAuditConfigurationTests; -import org.apereo.cas.audit.spi.config.CasCoreAuditConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasSupportCouchbaseAuditConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import org.apereo.inspektr.audit.AuditTrailManager; -import org.junit.jupiter.api.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; - -/** - * This is {@link CouchbaseAuditTrailManagerTests}. - * - * @author Misagh Moayyed - * @since 6.0.0 - * @deprecated since 7 - */ -@SpringBootTest(classes = { - CasCoreAuditConfiguration.class, - CasSupportCouchbaseAuditConfiguration.class, - CasCoreUtilConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - RefreshAutoConfiguration.class, - CasCoreWebConfiguration.class -}, properties = { - "cas.audit.couchbase.bucket=testbucket", - "cas.audit.couchbase.cluster-username=admin", - "cas.audit.couchbase.cluster-password=password", - "cas.audit.couchbase.asynchronous=false" -}) -@Tag("Couchbase") -@Getter -@EnabledIfListeningOnPort(port = 8091) -@Deprecated(since = "7.0.0") -public class CouchbaseAuditTrailManagerTests extends BaseAuditConfigurationTests { - @Autowired - @Qualifier("couchbaseAuditTrailManager") - private AuditTrailManager auditTrailManager; - - @Autowired - @Qualifier("auditsCouchbaseClientFactory") - private CouchbaseClientFactory auditsCouchbaseClientFactory; -} diff --git a/support/cas-server-support-audit-couchbase/src/test/resources/log4j2-test.xml b/support/cas-server-support-audit-couchbase/src/test/resources/log4j2-test.xml deleted file mode 100644 index 4e5c54d7c7d8..000000000000 --- a/support/cas-server-support-audit-couchbase/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-audit-couchdb/build.gradle b/support/cas-server-support-audit-couchdb/build.gradle deleted file mode 100644 index 210474c41666..000000000000 --- a/support/cas-server-support-audit-couchdb/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -description = "Apereo CAS MongoDb Audit Support" -ext { - publishMetadata = true - projectMetadata = [ - category: "Audits", - title: "Audits via Apache CouchDb" - ] -} - -dependencies { - api project(":api:cas-server-core-api") - api project(":api:cas-server-core-api-audit") - - implementation libraries.ektorp - - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-audit-api") - implementation project(":support:cas-server-support-couchdb-core") - - testImplementation project(":support:cas-server-support-person-directory") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-audit") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-web-api") - testImplementation project(":core:cas-server-core-configuration") - testImplementation project(path: ":core:cas-server-core-audit", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") -} diff --git a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/audit/CouchDbAuditTrailManager.java b/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/audit/CouchDbAuditTrailManager.java deleted file mode 100644 index 0ea3a9f2b8d3..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/audit/CouchDbAuditTrailManager.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.apereo.cas.audit; - -import org.apereo.cas.audit.spi.AbstractAuditTrailManager; -import org.apereo.cas.couchdb.audit.AuditActionContextCouchDbRepository; -import org.apereo.cas.couchdb.audit.CouchDbAuditActionContext; -import org.apereo.cas.util.CollectionUtils; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import org.apereo.inspektr.audit.AuditActionContext; - -import java.util.Map; -import java.util.Set; - -/** - * This is {@link CouchDbAuditTrailManager}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@AllArgsConstructor -@Getter -@Setter -@Deprecated(since = "7.0.0") -public class CouchDbAuditTrailManager extends AbstractAuditTrailManager { - private final AuditActionContextCouchDbRepository couchDb; - - public CouchDbAuditTrailManager(final boolean asynchronous, final AuditActionContextCouchDbRepository couchDb) { - super(asynchronous); - this.couchDb = couchDb; - } - - @Override - protected void saveAuditRecord(final AuditActionContext audit) { - couchDb.add(new CouchDbAuditActionContext(audit)); - } - - @Override - public Set getAuditRecords(final Map whereClause) { - return CollectionUtils.wrapHashSet(couchDb.findAuditRecords(whereClause)); - } -} diff --git a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/config/CasSupportCouchDbAuditConfiguration.java b/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/config/CasSupportCouchDbAuditConfiguration.java deleted file mode 100644 index 821c372df40d..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/config/CasSupportCouchDbAuditConfiguration.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer; -import org.apereo.cas.audit.CouchDbAuditTrailManager; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.audit.AuditActionContextCouchDbRepository; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import org.apereo.inspektr.audit.AuditTrailManager; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CasSupportCouchDbAuditConfiguration}. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Audit, module = "couchdb") -@AutoConfiguration -public class CasSupportCouchDbAuditConfiguration { - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "auditCouchDbFactory") - public CouchDbConnectorFactory auditCouchDbFactory( - final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory defaultObjectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getAudit().getCouchDb(), defaultObjectMapperFactory); - } - - @ConditionalOnMissingBean(name = "auditActionContextCouchDbRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuditActionContextCouchDbRepository auditActionContextCouchDbRepository( - @Qualifier("auditCouchDbFactory") - final CouchDbConnectorFactory auditCouchDbFactory, final CasConfigurationProperties casProperties) { - return new AuditActionContextCouchDbRepository(auditCouchDbFactory.getCouchDbConnector(), casProperties.getAudit().getCouchDb().isCreateIfNotExists()); - } - - @ConditionalOnMissingBean(name = "couchDbAuditTrailManager") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuditTrailManager couchDbAuditTrailManager( - @Qualifier("auditActionContextCouchDbRepository") - final AuditActionContextCouchDbRepository repository, final CasConfigurationProperties casProperties) { - return new CouchDbAuditTrailManager(casProperties.getAudit().getCouchDb().isAsynchronous(), repository); - } - - @ConditionalOnMissingBean(name = "couchDbAuditTrailExecutionPlanConfigurer") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuditTrailExecutionPlanConfigurer couchDbAuditTrailExecutionPlanConfigurer( - @Qualifier("couchDbAuditTrailManager") - final AuditTrailManager auditTrailManager) { - return plan -> plan.registerAuditTrailManager(auditTrailManager); - } -} diff --git a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/AuditActionContextCouchDbRepository.java b/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/AuditActionContextCouchDbRepository.java deleted file mode 100644 index 347f335a86e6..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/AuditActionContextCouchDbRepository.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apereo.cas.couchdb.audit; - -import lombok.Getter; -import lombok.val; -import org.apereo.inspektr.audit.AuditActionContext; -import org.apereo.inspektr.audit.AuditTrailManager; -import org.ektorp.ComplexKey; -import org.ektorp.CouchDbConnector; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.View; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.List; -import java.util.Map; - -/** - * This is {@link AuditActionContextCouchDbRepository}. DAO for CouchDb stored {@link AuditActionContext}s. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@Getter -@View(name = "all", map = "function(doc) { if(doc.whenActionWasPerformed) { emit(doc._id, doc) } }") -public class AuditActionContextCouchDbRepository extends CouchDbRepositorySupport { - - public AuditActionContextCouchDbRepository(final CouchDbConnector db, final boolean createIfNotExists) { - super(CouchDbAuditActionContext.class, db, createIfNotExists); - } - - /** - * Find audit records. - * - * @param whereClause the where clause - * @return the list - */ - @View(name = "by_when_action_was_performed", map = "classpath:by_when_params.js") - public List findAuditRecords(final Map whereClause) { - val localDate = ((LocalDate) whereClause.get(AuditTrailManager.WhereClauseFields.DATE)) - .atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli(); - val startKey = new StringBuilder(); - startKey.append(localDate); - if (whereClause.containsKey(AuditTrailManager.WhereClauseFields.PRINCIPAL)) { - startKey.append(whereClause.get(AuditTrailManager.WhereClauseFields.PRINCIPAL).toString()); - } - val query = createQuery("by_when_action_was_performed").startKey(startKey.toString()).includeDocs(true); - return db.queryView(query, CouchDbAuditActionContext.class); - } - - /** - * Find audit records for authentication throttling. - * - * @param remoteAddress remote IP address - * @param username username - * @param failureCode failure code - * @param applicationCode application code - * @param cutoffTime cut off time - * @return records for authentication throttling decision - */ - @View(name = "by_throttle_params", map = "classpath:by_throttle_params.js") - public List findByThrottleParams(final String remoteAddress, final String username, final String failureCode, - final String applicationCode, final LocalDateTime cutoffTime) { - val view = createQuery("by_throttle_params") - .startKey(ComplexKey.of(remoteAddress, username, failureCode, applicationCode, cutoffTime)) - .endKey(ComplexKey.of(remoteAddress, username, failureCode, applicationCode, "999999")); - return db.queryView(view, CouchDbAuditActionContext.class); - } -} diff --git a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/CouchDbAuditActionContext.java b/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/CouchDbAuditActionContext.java deleted file mode 100644 index 1525f02a8719..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/java/org/apereo/cas/couchdb/audit/CouchDbAuditActionContext.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.apereo.cas.couchdb.audit; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.Setter; -import org.apereo.inspektr.audit.AuditActionContext; - -import java.io.Serial; -import java.util.Date; - -/** - * This is {@link CouchDbAuditActionContext}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@Setter -@Deprecated(since = "7.0.0") -public class CouchDbAuditActionContext extends AuditActionContext { - @Serial - private static final long serialVersionUID = 5316526142085559254L; - - @JsonProperty("_id") - private String cid; - - @JsonProperty("_rev") - private String rev; - - @JsonCreator - public CouchDbAuditActionContext(@JsonProperty("_id") final String cid, - @JsonProperty("_rev") final String rev, - @JsonProperty("principal") final String principal, - @JsonProperty("resourceOperatedUpon") final String resourceOperatedUpon, - @JsonProperty("actionPerformed") final String actionPerformed, - @JsonProperty("applicationCode") final String applicationCode, - @JsonProperty("whenActionWasPerformed") final Date whenActionWasPerformed, - @JsonProperty("clientIpAddress") final String clientIpAddress, - @JsonProperty("serverIpAddress") final String serverIpAddress, - @JsonProperty("userAgent") final String userAgent) { - super(principal, resourceOperatedUpon, actionPerformed, applicationCode, - whenActionWasPerformed, clientIpAddress, serverIpAddress, userAgent); - this.cid = cid; - this.rev = rev; - } - - public CouchDbAuditActionContext(final AuditActionContext context) { - super(context.getPrincipal(), context.getResourceOperatedUpon(), - context.getActionPerformed(), context.getApplicationCode(), - context.getWhenActionWasPerformed(), context.getClientIpAddress(), - context.getServerIpAddress(), context.getUserAgent()); - } -} diff --git a/support/cas-server-support-audit-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-audit-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 02ccd0e5e254..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CasSupportCouchDbAuditConfiguration diff --git a/support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_throttle_params.js b/support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_throttle_params.js deleted file mode 100644 index 6850a117826b..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_throttle_params.js +++ /dev/null @@ -1,6 +0,0 @@ -function(doc) { - if (doc.clientIpAddress && doc.principal && doc.actionPerformed && doc.applicationCode && doc.whenActionWasPerformed){ - emit([doc.clientIpAddress, doc.principal, doc.actionPerformed, doc.applicationCode, doc.whenActionWasPerformed], doc) - } -} - diff --git a/support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_when_params.js b/support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_when_params.js deleted file mode 100644 index 846f00d442cd..000000000000 --- a/support/cas-server-support-audit-couchdb/src/main/resources/org/apereo/cas/couchdb/audit/by_when_params.js +++ /dev/null @@ -1,6 +0,0 @@ -function(doc) { - if (doc.whenActionWasPerformed && doc.principal) { - let d = new Date(doc.whenActionWasPerformed).getTime() + doc.principal - emit(d, doc) - } -} diff --git a/support/cas-server-support-audit-couchdb/src/test/java/org/apereo/cas/audit/CouchDbAuditTrailManagerTests.java b/support/cas-server-support-audit-couchdb/src/test/java/org/apereo/cas/audit/CouchDbAuditTrailManagerTests.java deleted file mode 100644 index f7d345a2f9ee..000000000000 --- a/support/cas-server-support-audit-couchdb/src/test/java/org/apereo/cas/audit/CouchDbAuditTrailManagerTests.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.apereo.cas.audit; - -import org.apereo.cas.audit.spi.BaseAuditConfigurationTests; -import org.apereo.cas.audit.spi.config.CasCoreAuditConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CasSupportCouchDbAuditConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.couchdb.audit.AuditActionContextCouchDbRepository; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import org.apereo.inspektr.audit.AuditTrailManager; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; - -/** - * This is {@link CouchDbAuditTrailManagerTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@SpringBootTest(classes = { - CasCoreAuditConfiguration.class, - CasSupportCouchDbAuditConfiguration.class, - CasCouchDbCoreConfiguration.class, - CasCoreUtilConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - RefreshAutoConfiguration.class, - CasCoreWebConfiguration.class -}, - properties = { - "cas.audit.couch-db.asynchronous=false", - "cas.audit.couch-db.username=cas", - "cas.audit.couch-db.caching=false", - "cas.audit.couch-db.password=password" - }) -@Tag("CouchDb") -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbAuditTrailManagerTests extends BaseAuditConfigurationTests { - - @Autowired - @Qualifier("auditActionContextCouchDbRepository") - private AuditActionContextCouchDbRepository couchDbRepository; - - @Autowired - @Qualifier("couchDbAuditTrailManager") - private AuditTrailManager auditTrailManager; - - @Autowired - @Qualifier("auditCouchDbFactory") - private CouchDbConnectorFactory auditCouchDbFactory; - - @BeforeEach - public void setUp() { - auditCouchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(auditCouchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initStandardDesignDocument(); - super.onSetUp(); - } -} diff --git a/support/cas-server-support-audit-couchdb/src/test/resources/log4j2-test.xml b/support/cas-server-support-audit-couchdb/src/test/resources/log4j2-test.xml deleted file mode 100644 index 578cca2cc3ed..000000000000 --- a/support/cas-server-support-audit-couchdb/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-aup-couchbase/build.gradle b/support/cas-server-support-aup-couchbase/build.gradle deleted file mode 100644 index ce9344d55f20..000000000000 --- a/support/cas-server-support-aup-couchbase/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -description = "Apereo CAS AUP Couchbase Support" -ext { - maxParallelForksForTests = 1 - publishMetadata = true - projectMetadata = [ - title: "Acceptable Usage Policy via Couchbase", - category: "Acceptable Usage Policy" - ] -} -dependencies { - api project(":api:cas-server-core-api") - api project(":api:cas-server-core-api-audit") - api project(":api:cas-server-core-api-authentication") - api project(":api:cas-server-core-api-ticket") - - api libraries.couchbase - - implementation project(":core:cas-server-core-authentication-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-web-api") - implementation project(":core:cas-server-core-webflow") - - implementation project(":support:cas-server-support-aup-core") - implementation project(":support:cas-server-support-aup-webflow") - implementation project(":support:cas-server-support-couchbase-core") - - testImplementation project(":core:cas-server-core") - testImplementation project(":core:cas-server-core-audit") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-authentication-mfa") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-webflow-mfa") - testImplementation project(":core:cas-server-core-cookie") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-notifications") - - testImplementation project(path: ":core:cas-server-core", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-tickets", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-aup-core", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-aup-webflow", configuration: "tests") -} diff --git a/support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepository.java b/support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepository.java deleted file mode 100644 index 96d92f1d5b90..000000000000 --- a/support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepository.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.apereo.cas.aup; - -import org.apereo.cas.configuration.model.support.aup.AcceptableUsagePolicyProperties; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.ticket.registry.TicketRegistrySupport; -import org.apereo.cas.util.LoggingUtils; -import org.apereo.cas.util.serialization.JacksonObjectMapperFactory; -import org.apereo.cas.web.support.WebUtils; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.springframework.webflow.execution.RequestContext; - -import java.io.Serial; -import java.util.Map; - -/** - * This is {@link CouchbaseAcceptableUsagePolicyRepository}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated since 7.0.0 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchbaseAcceptableUsagePolicyRepository extends BaseAcceptableUsagePolicyRepository { - @Serial - private static final long serialVersionUID = -1276731330180695089L; - - private static final ObjectMapper MAPPER = JacksonObjectMapperFactory.builder() - .defaultTypingEnabled(false).build().toObjectMapper(); - - private final CouchbaseClientFactory couchbase; - - public CouchbaseAcceptableUsagePolicyRepository(final TicketRegistrySupport ticketRegistrySupport, - final AcceptableUsagePolicyProperties aupProperties, - final CouchbaseClientFactory couchbase) { - super(ticketRegistrySupport, aupProperties); - this.couchbase = couchbase; - } - - @Override - public boolean submit(final RequestContext requestContext) { - try { - val principal = WebUtils.getAuthentication(requestContext).getPrincipal(); - val content = MAPPER.writeValueAsString(Map.of( - "username", principal.getId(), - aupProperties.getCore().getAupAttributeName(), Boolean.TRUE)); - couchbase.bucketUpsertDefaultCollection(content); - return true; - } catch (final Exception e) { - LoggingUtils.error(LOGGER, e); - } - return false; - } -} diff --git a/support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchbaseConfiguration.java b/support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchbaseConfiguration.java deleted file mode 100644 index 4ed7ade2408a..000000000000 --- a/support/cas-server-support-aup-couchbase/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchbaseConfiguration.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.aup.AcceptableUsagePolicyRepository; -import org.apereo.cas.aup.CouchbaseAcceptableUsagePolicyRepository; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.couchbase.core.DefaultCouchbaseClientFactory; -import org.apereo.cas.ticket.registry.TicketRegistrySupport; -import org.apereo.cas.util.spring.beans.BeanSupplier; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CasAcceptableUsagePolicyCouchbaseConfiguration} that stores AUP decisions in a mongo database. - * - * @author Misagh Moayyed - * @since 5.2.0 - * @deprecated Since 7.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.AcceptableUsagePolicy, module = "couchbase") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CasAcceptableUsagePolicyCouchbaseConfiguration { - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - public CouchbaseClientFactory aupCouchbaseClientFactory(final CasConfigurationProperties casProperties) { - val cb = casProperties.getAcceptableUsagePolicy().getCouchbase(); - return new DefaultCouchbaseClientFactory(cb); - } - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - public AcceptableUsagePolicyRepository acceptableUsagePolicyRepository( - final ConfigurableApplicationContext applicationContext, - final CasConfigurationProperties casProperties, - @Qualifier("aupCouchbaseClientFactory") - final CouchbaseClientFactory aupCouchbaseClientFactory, - @Qualifier(TicketRegistrySupport.BEAN_NAME) - final TicketRegistrySupport ticketRegistrySupport) throws Exception { - return BeanSupplier.of(AcceptableUsagePolicyRepository.class) - .when(AcceptableUsagePolicyRepository.CONDITION_AUP_ENABLED.given(applicationContext.getEnvironment())) - .supply(() -> new CouchbaseAcceptableUsagePolicyRepository(ticketRegistrySupport, - casProperties.getAcceptableUsagePolicy(), aupCouchbaseClientFactory)) - .otherwise(AcceptableUsagePolicyRepository::noOp) - .get(); - } -} diff --git a/support/cas-server-support-aup-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-aup-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 8ffd65fc431e..000000000000 --- a/support/cas-server-support-aup-couchbase/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CasAcceptableUsagePolicyCouchbaseConfiguration diff --git a/support/cas-server-support-aup-couchbase/src/test/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepositoryTests.java b/support/cas-server-support-aup-couchbase/src/test/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepositoryTests.java deleted file mode 100644 index 94dbae8f4628..000000000000 --- a/support/cas-server-support-aup-couchbase/src/test/java/org/apereo/cas/aup/CouchbaseAcceptableUsagePolicyRepositoryTests.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.apereo.cas.aup; - -import org.apereo.cas.config.CasAcceptableUsagePolicyCouchbaseConfiguration; -import org.apereo.cas.util.CollectionUtils; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import lombok.val; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.TestPropertySource; - -import java.util.List; -import java.util.UUID; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchbaseAcceptableUsagePolicyRepositoryTests}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated since 7.0.0 - */ -@Import({ - CasAcceptableUsagePolicyCouchbaseConfiguration.class, - BaseAcceptableUsagePolicyRepositoryTests.SharedTestConfiguration.class -}) -@TestPropertySource( - properties = { - "cas.acceptable-usage-policy.couchbase.bucket=testbucket", - "cas.acceptable-usage-policy.couchbase.cluster-username=admin", - "cas.acceptable-usage-policy.couchbase.cluster-password=password" - }) -@Tag("Couchbase") -@EnabledIfListeningOnPort(port = 8091) -@Getter -@Deprecated(since = "7.0.0") -public class CouchbaseAcceptableUsagePolicyRepositoryTests extends BaseAcceptableUsagePolicyRepositoryTests { - @Autowired - @Qualifier(AcceptableUsagePolicyRepository.BEAN_NAME) - protected AcceptableUsagePolicyRepository acceptableUsagePolicyRepository; - - @Test - public void verifyOperation() throws Exception { - assertNotNull(acceptableUsagePolicyRepository); - val id = UUID.randomUUID().toString(); - verifyRepositoryAction(id, - CollectionUtils.wrap( - "accepted", List.of("false"), - "email", List.of("CASuser@example.org"))); - } -} diff --git a/support/cas-server-support-aup-couchbase/src/test/resources/log4j2-test.xml b/support/cas-server-support-aup-couchbase/src/test/resources/log4j2-test.xml deleted file mode 100644 index 83be0d3b98f7..000000000000 --- a/support/cas-server-support-aup-couchbase/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-aup-couchdb/build.gradle b/support/cas-server-support-aup-couchdb/build.gradle deleted file mode 100644 index c68d7d681150..000000000000 --- a/support/cas-server-support-aup-couchdb/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -description = "Apereo CAS AUP CouchDb Support" -ext { - maxParallelForksForTests = 1 - publishMetadata = true - projectMetadata = [ - title: "Acceptable Usage Policy via Apache CouchDb", - category: "Acceptable Usage Policy" - ] -} -dependencies { - api project(":api:cas-server-core-api-authentication") - api project(":api:cas-server-core-api-ticket") - - implementation project(":core:cas-server-core-authentication-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-web-api") - implementation project(":core:cas-server-core-services-api") - implementation project(":core:cas-server-core-webflow") - implementation project(":support:cas-server-support-aup-core") - implementation project(":support:cas-server-support-aup-webflow") - implementation project(":support:cas-server-support-couchdb-core") - - api libraries.ektorp - - testImplementation project(":core:cas-server-core") - testImplementation project(":core:cas-server-core-audit") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-authentication-mfa") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-webflow-mfa") - testImplementation project(":core:cas-server-core-cookie") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-notifications") - - testImplementation project(path: ":core:cas-server-core", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-tickets", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-aup-core", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-aup-webflow", configuration: "tests") -} diff --git a/support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepository.java b/support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepository.java deleted file mode 100644 index 8a1f19adb413..000000000000 --- a/support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepository.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.apereo.cas.aup; - -import org.apereo.cas.configuration.model.support.aup.AcceptableUsagePolicyProperties; -import org.apereo.cas.couchdb.core.CouchDbProfileDocument; -import org.apereo.cas.couchdb.core.ProfileCouchDbRepository; -import org.apereo.cas.ticket.registry.TicketRegistrySupport; -import org.apereo.cas.util.CollectionUtils; -import org.apereo.cas.util.model.TriStateBoolean; -import org.apereo.cas.web.support.WebUtils; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.ektorp.UpdateConflictException; -import org.springframework.webflow.execution.RequestContext; - -import java.io.Serial; -import java.util.List; - -/** - * This is {@link CouchDbAcceptableUsagePolicyRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchDbAcceptableUsagePolicyRepository extends BaseAcceptableUsagePolicyRepository { - - @Serial - private static final long serialVersionUID = -2391630070546362552L; - - private final transient ProfileCouchDbRepository couchDb; - - private final int conflictRetries; - - public CouchDbAcceptableUsagePolicyRepository(final TicketRegistrySupport ticketRegistrySupport, - final AcceptableUsagePolicyProperties properties, - final ProfileCouchDbRepository couchDb, - final int conflictRetries) { - super(ticketRegistrySupport, properties); - this.couchDb = couchDb; - this.conflictRetries = conflictRetries; - } - - @Override - public AcceptableUsagePolicyStatus verify(final RequestContext requestContext) { - var status = super.verify(requestContext); - if (status.isDenied()) { - val principal = WebUtils.getAuthentication(requestContext).getPrincipal(); - val profile = couchDb.findByUsername(principal.getId()); - var accepted = false; - if (profile != null) { - val values = CollectionUtils.toCollection(profile.getAttribute(aupProperties.getCore().getAupAttributeName())); - accepted = CollectionUtils.firstElement(values).map(value -> (Boolean) value).orElse(Boolean.FALSE); - } - if (accepted) { - LOGGER.debug("Acceptable usage policy has been accepted by [{}]", profile.getUsername()); - } - status = new AcceptableUsagePolicyStatus(TriStateBoolean.fromBoolean(accepted), status.getPrincipal()); - } - return status; - } - - @Override - public boolean submit(final RequestContext requestContext) { - val principal = WebUtils.getAuthentication(requestContext).getPrincipal(); - val username = principal.getId(); - val profile = couchDb.findByUsername(username); - if (profile == null) { - val doc = new CouchDbProfileDocument(username, null, - CollectionUtils.wrap(aupProperties.getCore().getAupAttributeName(), List.of(Boolean.TRUE))); - couchDb.add(doc); - return true; - } - var success = false; - profile.setAttribute(aupProperties.getCore().getAupAttributeName(), List.of(Boolean.TRUE)); - UpdateConflictException exception = null; - for (var retries = 0; !success && retries < conflictRetries; retries++) { - try { - couchDb.update(profile); - success = true; - } catch (final Exception e) { - LOGGER.debug("Could not update AUP acceptance for [{}].\n[{}]", username, exception); - } - } - if (success) { - LOGGER.debug("Successfully updated AUP for [{}].", profile.getUsername()); - } - return success; - } -} diff --git a/support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchDbConfiguration.java b/support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchDbConfiguration.java deleted file mode 100644 index 6e0b537dd79d..000000000000 --- a/support/cas-server-support-aup-couchdb/src/main/java/org/apereo/cas/config/CasAcceptableUsagePolicyCouchDbConfiguration.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.aup.AcceptableUsagePolicyRepository; -import org.apereo.cas.aup.CouchDbAcceptableUsagePolicyRepository; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultProfileCouchDbRepository; -import org.apereo.cas.couchdb.core.ProfileCouchDbRepository; -import org.apereo.cas.ticket.registry.TicketRegistrySupport; -import org.apereo.cas.util.spring.beans.BeanSupplier; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CasAcceptableUsagePolicyCouchDbConfiguration} that stores AUP decisions in a CouchDb database. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.AcceptableUsagePolicy, module = "couchdb") -@AutoConfiguration -public class CasAcceptableUsagePolicyCouchDbConfiguration { - - @ConditionalOnMissingBean(name = "aupCouchDbFactory") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CouchDbConnectorFactory aupCouchDbFactory( - final ConfigurableApplicationContext applicationContext, - final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) throws Exception { - return BeanSupplier.of(CouchDbConnectorFactory.class) - .when(AcceptableUsagePolicyRepository.CONDITION_AUP_ENABLED.given(applicationContext.getEnvironment())) - .supply(() -> new DefaultCouchDbConnectorFactory(casProperties.getAcceptableUsagePolicy().getCouchDb(), objectMapperFactory)) - .otherwiseProxy() - .get(); - } - - @ConditionalOnMissingBean(name = "aupCouchDbRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public ProfileCouchDbRepository aupCouchDbRepository( - final ConfigurableApplicationContext applicationContext, - @Qualifier("aupCouchDbFactory") - final CouchDbConnectorFactory aupCouchDbFactory, - final CasConfigurationProperties casProperties) throws Exception { - return BeanSupplier.of(ProfileCouchDbRepository.class) - .when(AcceptableUsagePolicyRepository.CONDITION_AUP_ENABLED.given(applicationContext.getEnvironment())) - .supply(() -> { - val couchDb = casProperties.getAcceptableUsagePolicy().getCouchDb(); - return new DefaultProfileCouchDbRepository(aupCouchDbFactory.getCouchDbConnector(), couchDb.isCreateIfNotExists()); - }) - .otherwiseProxy() - .get(); - } - - @ConditionalOnMissingBean(name = "couchDbAcceptableUsagePolicyRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AcceptableUsagePolicyRepository acceptableUsagePolicyRepository( - @Qualifier("aupCouchDbRepository") - final ProfileCouchDbRepository profileCouchDbRepository, - final ConfigurableApplicationContext applicationContext, - final CasConfigurationProperties casProperties, - @Qualifier(TicketRegistrySupport.BEAN_NAME) - final TicketRegistrySupport ticketRegistrySupport) throws Exception { - return BeanSupplier.of(AcceptableUsagePolicyRepository.class) - .when(AcceptableUsagePolicyRepository.CONDITION_AUP_ENABLED.given(applicationContext.getEnvironment())) - .supply(() -> new CouchDbAcceptableUsagePolicyRepository(ticketRegistrySupport, - casProperties.getAcceptableUsagePolicy(), profileCouchDbRepository, - casProperties.getAcceptableUsagePolicy().getCouchDb().getRetries())) - .otherwise(AcceptableUsagePolicyRepository::noOp) - .get(); - } -} diff --git a/support/cas-server-support-aup-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-aup-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index f5894463990b..000000000000 --- a/support/cas-server-support-aup-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CasAcceptableUsagePolicyCouchDbConfiguration diff --git a/support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java b/support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java deleted file mode 100644 index c16a1bd1f3dd..000000000000 --- a/support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.apereo.cas; - -import org.apereo.cas.aup.CouchDbAcceptableUsagePolicyRepositoryTests; - -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; - -/** - * This is {@link AllTestsSuite}. - * - * @author Misagh Moayyed - * @since 6.0.0-RC3 - */ -@SelectClasses(CouchDbAcceptableUsagePolicyRepositoryTests.class) -@Suite -public class AllTestsSuite { -} diff --git a/support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepositoryTests.java b/support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepositoryTests.java deleted file mode 100644 index 6e6179759c3f..000000000000 --- a/support/cas-server-support-aup-couchdb/src/test/java/org/apereo/cas/aup/CouchDbAcceptableUsagePolicyRepositoryTests.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.apereo.cas.aup; - -import org.apereo.cas.config.CasAcceptableUsagePolicyCouchDbConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.ProfileCouchDbRepository; -import org.apereo.cas.mock.MockTicketGrantingTicket; -import org.apereo.cas.services.RegisteredServiceTestUtils; -import org.apereo.cas.util.CollectionUtils; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; -import org.apereo.cas.web.support.WebUtils; - -import lombok.Getter; -import lombok.val; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.TestPropertySource; - -import java.util.List; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchDbAcceptableUsagePolicyRepositoryTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Import({ - CasCouchDbCoreConfiguration.class, - CasAcceptableUsagePolicyCouchDbConfiguration.class, - BaseAcceptableUsagePolicyRepositoryTests.SharedTestConfiguration.class -}) -@TestPropertySource(properties = { - "cas.acceptable-usage-policy.couch-db.asynchronous=false", - "cas.acceptable-usage-policy.couch-db.username=cas", - "cas.acceptable-usage-policy.couch-db.password=password" -}) -@Tag("CouchDb") -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbAcceptableUsagePolicyRepositoryTests extends BaseAcceptableUsagePolicyRepositoryTests { - - @Autowired - @Qualifier("aupCouchDbFactory") - private CouchDbConnectorFactory aupCouchDbFactory; - - @Autowired - @Qualifier("aupCouchDbRepository") - private ProfileCouchDbRepository couchDbRepository; - - @Autowired - @Qualifier(AcceptableUsagePolicyRepository.BEAN_NAME) - private AcceptableUsagePolicyRepository acceptableUsagePolicyRepository; - - @BeforeEach - public void setUp() { - aupCouchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(aupCouchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initialize(); - } - - @AfterEach - public void tearDown() { - aupCouchDbFactory.getCouchDbInstance().deleteDatabase(aupCouchDbFactory.getCouchDbConnector().getDatabaseName()); - } - - @Override - public boolean hasLiveUpdates() { - return true; - } - - @Test - public void verifyOperation() throws Exception { - assertNotNull(acceptableUsagePolicyRepository); - val attributes = CollectionUtils.>wrap("aupAccepted", List.of("false"), - "email", List.of("CASuser@example.org")); - verifyRepositoryAction("casuser", attributes); - - val c = getCredential("casuser"); - val context = getRequestContext("casuser", attributes, c); - acceptableUsagePolicyRepository.submit(context); - assertTrue(getAcceptableUsagePolicyRepository().verify(context).isAccepted()); - - val principal = RegisteredServiceTestUtils.getPrincipal("casuser", Map.of("aupAccepted", List.of("true"))); - val authentication = RegisteredServiceTestUtils.getAuthentication(principal); - WebUtils.putAuthentication(authentication, context); - - val tgt = new MockTicketGrantingTicket(authentication); - WebUtils.putTicketGrantingTicketInScopes(context, tgt); - ticketRegistry.addTicket(tgt); - - assertTrue(getAcceptableUsagePolicyRepository().verify(context).isAccepted()); - } -} diff --git a/support/cas-server-support-aup-couchdb/src/test/resources/log4j2-test.xml b/support/cas-server-support-aup-couchdb/src/test/resources/log4j2-test.xml deleted file mode 100644 index 83be0d3b98f7..000000000000 --- a/support/cas-server-support-aup-couchdb/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-consent-couchdb/build.gradle b/support/cas-server-support-consent-couchdb/build.gradle deleted file mode 100644 index 990f61d1bc6f..000000000000 --- a/support/cas-server-support-consent-couchdb/build.gradle +++ /dev/null @@ -1,45 +0,0 @@ -description = "Apereo CAS Consent Support via CouchDbDb" -ext { - publishMetadata = true - projectMetadata = [ - title: "Attribute Consent via Apache CouchDb", - category: "Attribute Consent" - ] -} - -dependencies { - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":core:cas-server-core-authentication-api") - implementation project(":core:cas-server-core-web-api") - implementation project(":core:cas-server-core-services-api") - implementation project(":support:cas-server-support-couchdb-core") - implementation project(":support:cas-server-support-consent-api") - implementation project(":support:cas-server-support-consent-core") - - implementation libraries.ektorp - - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-configuration") - testImplementation project(":core:cas-server-core-audit") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core") - testImplementation project(":core:cas-server-core-cookie") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-authentication-attributes") - testImplementation project(":core:cas-server-core-authentication-mfa") - testImplementation project(":core:cas-server-core-webflow-mfa") - testImplementation project(":core:cas-server-core-webflow") - - testImplementation project(":core:cas-server-core-notifications") - - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-consent-core", configuration: "tests") -} diff --git a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/config/CasConsentCouchDbConfiguration.java b/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/config/CasConsentCouchDbConfiguration.java deleted file mode 100644 index 3939f3336714..000000000000 --- a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/config/CasConsentCouchDbConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.consent.ConsentRepository; -import org.apereo.cas.consent.CouchDbConsentRepository; -import org.apereo.cas.couchdb.consent.ConsentDecisionCouchDbRepository; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CasConsentCouchDbConfiguration}. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Consent, module = "couchdb") -@AutoConfiguration -public class CasConsentCouchDbConfiguration { - - @ConditionalOnMissingBean(name = "consentCouchDbFactory") - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - public CouchDbConnectorFactory consentCouchDbFactory( - final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getConsent().getCouchDb(), objectMapperFactory); - } - - @ConditionalOnMissingBean(name = "consentCouchDbRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public ConsentDecisionCouchDbRepository consentCouchDbRepository( - @Qualifier("consentCouchDbFactory") - final CouchDbConnectorFactory consentCouchDbFactory, - final CasConfigurationProperties casProperties) { - val repository = new ConsentDecisionCouchDbRepository(consentCouchDbFactory.getCouchDbConnector(), - consentCouchDbFactory.getCouchDbInstance(), - casProperties.getConsent().getCouchDb().isCreateIfNotExists()); - repository.initStandardDesignDocument(); - return repository; - } - - @ConditionalOnMissingBean(name = "couchDbConsentRepository") - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - public ConsentRepository consentRepository( - @Qualifier("consentCouchDbRepository") - final ConsentDecisionCouchDbRepository consentCouchDbRepository) { - return new CouchDbConsentRepository(consentCouchDbRepository); - } -} diff --git a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/consent/CouchDbConsentRepository.java b/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/consent/CouchDbConsentRepository.java deleted file mode 100644 index 9adde5cbf9d5..000000000000 --- a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/consent/CouchDbConsentRepository.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.apereo.cas.consent; - -import org.apereo.cas.authentication.Authentication; -import org.apereo.cas.authentication.principal.Service; -import org.apereo.cas.couchdb.consent.ConsentDecisionCouchDbRepository; -import org.apereo.cas.couchdb.consent.CouchDbConsentDecision; -import org.apereo.cas.services.RegisteredService; -import org.apereo.cas.util.LoggingUtils; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; - -import java.io.Serial; -import java.util.Collection; -import java.util.stream.Collectors; - -/** - * This is {@link CouchDbConsentRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public record CouchDbConsentRepository(ConsentDecisionCouchDbRepository couchDb) implements ConsentRepository { - - @Serial - private static final long serialVersionUID = 5058836218210655958L; - - @Override - public ConsentDecision findConsentDecision(final Service service, final RegisteredService registeredService, - final Authentication authentication) { - return couchDb.findFirstConsentDecision(authentication.getPrincipal().getId(), service.getId()); - } - - @Override - public Collection findConsentDecisions(final String principal) { - return couchDb.findByPrincipal(principal).stream().map(c -> (ConsentDecision) c).collect(Collectors.toList()); - } - - @Override - public Collection findConsentDecisions() { - return couchDb.getAll().stream().map(c -> (ConsentDecision) c).collect(Collectors.toList()); - } - - @Override - public ConsentDecision storeConsentDecision(final ConsentDecision decision) { - try { - val consent = couchDb.findFirstConsentDecision(decision); - var updated = (CouchDbConsentDecision) null; - if (consent == null) { - updated = new CouchDbConsentDecision(decision); - couchDb.add(updated); - } else { - updated = consent.copyDetailsFrom(decision); - couchDb.update(updated); - } - return updated; - } catch (final Exception e) { - LoggingUtils.warn(LOGGER, "Failure storing consent decision", e); - return null; - } - } - - @Override - public boolean deleteConsentDecision(final long id, final String principal) { - try { - val consent = couchDb.findByPrincipalAndId(principal, id); - if (consent != null) { - couchDb.remove(consent); - return true; - } - } catch (final Exception e) { - LoggingUtils.warn(LOGGER, "Failure deleting consent decision", e); - } - return false; - } - - @Override - public boolean deleteConsentDecisions(final String principal) { - val consent = couchDb.findByPrincipal(principal); - if (consent != null) { - consent.forEach(couchDb::remove); - return true; - } - return false; - } - - @Override - public void deleteAll() { - couchDb.removeAll(); - } -} diff --git a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/ConsentDecisionCouchDbRepository.java b/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/ConsentDecisionCouchDbRepository.java deleted file mode 100644 index 9e72d7b61b34..000000000000 --- a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/ConsentDecisionCouchDbRepository.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.apereo.cas.couchdb.consent; - -import org.apereo.cas.consent.ConsentDecision; -import org.apereo.cas.util.function.FunctionUtils; - -import lombok.val; -import org.ektorp.ComplexKey; -import org.ektorp.CouchDbConnector; -import org.ektorp.CouchDbInstance; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.GenerateView; -import org.ektorp.support.View; -import org.jooq.lambda.fi.util.function.CheckedFunction; - -import java.util.List; - -/** - * This is {@link ConsentDecisionCouchDbRepository}. DAO for CouchDb stored {@link ConsentDecision}s. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@View(name = "all", map = "function(doc) { emit(doc._id, doc) }") -public class ConsentDecisionCouchDbRepository extends CouchDbRepositorySupport { - private final CouchDbInstance couchDbInstance; - - public ConsentDecisionCouchDbRepository(final CouchDbConnector db, - final CouchDbInstance couchDbInstance, - final boolean createIfNotExists) { - super(CouchDbConsentDecision.class, db, createIfNotExists); - this.couchDbInstance = couchDbInstance; - } - - /** - * Find {@link ConsentDecision} belonging to a principal. - * - * @param principal to search for. - * @return All entries for the given principal. - */ - @GenerateView - public List findByPrincipal(final String principal) { - return queryView("by_principal", principal); - } - - /** - * Find all consent decisions for a given principal, service pair. Should only be one. - * - * @param principal User to search for. - * @param service Service name to search for. - * @return Consent decisions matching the given principal and service names. - */ - @View(name = "by_consent_decision", map = "function(doc) {emit([doc.principal, doc.service], doc)}") - public List findConsentDecision(final String principal, final String service) { - val view = createQuery("by_consent_decision").key(ComplexKey.of(principal, service)).includeDocs(true); - return db.queryView(view, CouchDbConsentDecision.class); - } - - /** - * Find the first consent decision for a given principal, service pair. Should only be one of them anyway. - * - * @param principal User to search for. - * @param service Service name to search for. - * @return Consent decision matching the given principal and service names. - */ - public CouchDbConsentDecision findFirstConsentDecision(final String principal, final String service) { - val view = createQuery("by_consent_decision").key(ComplexKey.of(principal, service)).limit(1).includeDocs(true); - return db.queryView(view, CouchDbConsentDecision.class).stream().findFirst().orElse(null); - } - - /** - * Find the first consent decision for a given {@link ConsentDecision}. Should only be one of them anyway. - * - * @param consent Consent decision to search for - * @return Consent decision matching the given principal and service names in the consent decision provided. - */ - public CouchDbConsentDecision findFirstConsentDecision(final ConsentDecision consent) { - return findFirstConsentDecision(consent.getPrincipal(), consent.getService()); - } - - /** - * Find a consent decision by +long+ ID and principal name. For CouchDb, this ID is randomly generated and the pair should be unique, with a very high - * probability, but is not guaranteed. This method is mostly only used by tests. - * - * @param principal User to search for. - * @param id decision id to search for. - * @return First consent decision matching principal and id. - */ - @View(name = "by_principal_and_id", map = "function(doc) {emit([doc.principal, doc.id], doc)}") - public CouchDbConsentDecision findByPrincipalAndId(final String principal, final long id) { - val view = createQuery("by_principal_and_id") - .key(ComplexKey.of(principal, String.valueOf(id))).limit(1).includeDocs(true); - return db.queryView(view, CouchDbConsentDecision.class).stream().findFirst().orElse(null); - } - - /** - * Remove all. - */ - public void removeAll() { - FunctionUtils.doAndHandle(__ -> { - if (couchDbInstance.checkIfDbExists(db.getDatabaseName())) { - couchDbInstance.deleteDatabase(db.getDatabaseName()); - } - couchDbInstance.createDatabaseIfNotExists(db.getDatabaseName()); - initStandardDesignDocument(); - }, (CheckedFunction) throwable -> null).accept(null); - } -} diff --git a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/CouchDbConsentDecision.java b/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/CouchDbConsentDecision.java deleted file mode 100644 index eb0df5d78d78..000000000000 --- a/support/cas-server-support-consent-couchdb/src/main/java/org/apereo/cas/couchdb/consent/CouchDbConsentDecision.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.apereo.cas.couchdb.consent; - -import org.apereo.cas.consent.ConsentDecision; -import org.apereo.cas.consent.ConsentReminderOptions; -import org.apereo.cas.util.RandomUtils; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import lombok.Getter; -import lombok.Setter; - -import java.io.Serial; -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; - -/** - * This is {@link CouchDbConsentDecision}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@Setter -@Deprecated(since = "7.0.0") -public class CouchDbConsentDecision extends ConsentDecision { - @Serial - private static final long serialVersionUID = -685282558102325489L; - - @JsonProperty("_rev") - private String rev; - - @JsonProperty("_id") - private String cid; - - @JsonCreator - public CouchDbConsentDecision(@JsonProperty("_id") final String cid, - @JsonProperty("_rev") final String rev, - @JsonProperty("id") final long id, - @JsonProperty("principal") final String principal, - @JsonProperty("service") final String service, - @JsonProperty("createdDate") final LocalDateTime createdDate, - @JsonProperty("options") final ConsentReminderOptions options, - @JsonProperty("reminder") final long reminder, - @JsonProperty("reminderTimeUnit") final ChronoUnit reminderTimeUnit, - @JsonProperty("attributes") final String attributes) { - this.cid = cid; - this.rev = rev; - setId(id); - setPrincipal(principal); - setService(service); - setCreatedDate(createdDate); - setOptions(options); - setReminder(reminder); - setReminderTimeUnit(reminderTimeUnit); - setAttributes(attributes); - } - - /** - * Copy constructor. - * - * @param c Consent decision to copy from. - */ - public CouchDbConsentDecision(final ConsentDecision c) { - setAttributes(c.getAttributes()); - setPrincipal(c.getPrincipal()); - setCreatedDate(c.getCreatedDate()); - setId(c.getId()); - setOptions(c.getOptions()); - setReminder(c.getReminder()); - setReminderTimeUnit(c.getReminderTimeUnit()); - setService(c.getService()); - if (getId() < 0) { - setId(RandomUtils.nextLong()); - } - } - - /** - * Copy consent details to this instance. - * - * @param other decision to copy details from. - * @return CouchDb capable consent decision. - */ - @CanIgnoreReturnValue - public CouchDbConsentDecision copyDetailsFrom(final ConsentDecision other) { - setAttributes(other.getAttributes()); - setPrincipal(other.getPrincipal()); - setCreatedDate(other.getCreatedDate()); - setId(other.getId()); - setOptions(other.getOptions()); - setReminder(other.getReminder()); - setReminderTimeUnit(other.getReminderTimeUnit()); - setService(other.getService()); - return this; - } -} diff --git a/support/cas-server-support-consent-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-consent-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index d97c79efcd6a..000000000000 --- a/support/cas-server-support-consent-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CasConsentCouchDbConfiguration diff --git a/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java b/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java deleted file mode 100644 index 680e6e033594..000000000000 --- a/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.apereo.cas; - -import org.apereo.cas.consent.CouchDbConsentDecisionTests; -import org.apereo.cas.consent.CouchDbConsentRepositoryTests; - -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; - -/** - * This is {@link AllTestsSuite}. - * - * @author Misagh Moayyed - * @since 6.0.0-RC3 - */ -@SelectClasses({ - CouchDbConsentDecisionTests.class, - CouchDbConsentRepositoryTests.class -}) -@Suite -public class AllTestsSuite { -} diff --git a/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentDecisionTests.java b/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentDecisionTests.java deleted file mode 100644 index 91019455c269..000000000000 --- a/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentDecisionTests.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.apereo.cas.consent; - -import org.apereo.cas.config.CasConsentCouchDbConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.couchdb.consent.CouchDbConsentDecision; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import lombok.val; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.temporal.ChronoUnit; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchDbConsentDecisionTests}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7 - */ -@SpringBootTest(classes = { - CasCouchDbCoreConfiguration.class, - CasConsentCouchDbConfiguration.class, - BaseConsentRepositoryTests.SharedTestConfiguration.class -}, - properties = { - "cas.consent.couch-db.username=cas", - "cas.consent.couch-db.password=password", - "cas.consent.couch-db.caching=false" - }) -@Tag("CouchDb") -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbConsentDecisionTests { - @Test - public void verifyOperation() { - val consent = new ConsentDecision(); - consent.setAttributes("attributes"); - consent.setCreatedDate(LocalDateTime.now(ZoneId.systemDefault())); - consent.setOptions(ConsentReminderOptions.ATTRIBUTE_NAME); - consent.setPrincipal("casuser"); - consent.setReminder(10L); - consent.setReminderTimeUnit(ChronoUnit.MONTHS); - consent.setService("service"); - - val decision = new CouchDbConsentDecision(consent); - assertEquals(decision, decision.copyDetailsFrom(consent)); - } - -} diff --git a/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentRepositoryTests.java b/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentRepositoryTests.java deleted file mode 100644 index 9ce49f877db1..000000000000 --- a/support/cas-server-support-consent-couchdb/src/test/java/org/apereo/cas/consent/CouchDbConsentRepositoryTests.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apereo.cas.consent; - -import org.apereo.cas.config.CasConsentCouchDbConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.couchdb.consent.ConsentDecisionCouchDbRepository; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import lombok.val; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * This is {@link CouchDbConsentRepositoryTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@SpringBootTest(classes = { - CasCouchDbCoreConfiguration.class, - CasConsentCouchDbConfiguration.class, - BaseConsentRepositoryTests.SharedTestConfiguration.class -}, - properties = { - "cas.consent.couch-db.username=cas", - "cas.consent.couch-db.password=password", - "cas.consent.couch-db.caching=false" - }) -@Tag("CouchDb") -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbConsentRepositoryTests extends BaseConsentRepositoryTests { - - @Autowired - @Qualifier("consentCouchDbFactory") - private CouchDbConnectorFactory couchDbFactory; - - @Autowired - @Qualifier("consentCouchDbRepository") - private ConsentDecisionCouchDbRepository couchDbRepository; - - @Autowired - @Qualifier(ConsentRepository.BEAN_NAME) - private ConsentRepository repository; - - @BeforeEach - public void setUp() { - repository.deleteAll(); - couchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(couchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initStandardDesignDocument(); - } - - @AfterEach - public void tearDown() { - couchDbFactory.getCouchDbInstance().deleteDatabase(couchDbFactory.getCouchDbConnector().getDatabaseName()); - } - - @Test - public void verifyFailsOperation() { - assertTrue(couchDbRepository.findConsentDecision("unknown", "unknown").isEmpty()); - val decision = BUILDER.build(SVC, REG_SVC, "casuser", ATTR); - val mockRepo = mock(ConsentDecisionCouchDbRepository.class); - when(mockRepo.findFirstConsentDecision(any(ConsentDecision.class))).thenThrow(new RuntimeException()); - when(mockRepo.findByPrincipalAndId(anyString(), anyLong())).thenThrow(new RuntimeException()); - assertNull(new CouchDbConsentRepository(mockRepo).storeConsentDecision(decision)); - assertFalse(new CouchDbConsentRepository(mockRepo).deleteConsentDecision(1, "casuser")); - } - -} diff --git a/support/cas-server-support-consent-couchdb/src/test/resources/log4j2-test.xml b/support/cas-server-support-consent-couchdb/src/test/resources/log4j2-test.xml deleted file mode 100644 index 3a3fa4f1f17f..000000000000 --- a/support/cas-server-support-consent-couchdb/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/support/cas-server-support-couchbase-authentication/build.gradle b/support/cas-server-support-couchbase-authentication/build.gradle deleted file mode 100644 index f6308f6614b2..000000000000 --- a/support/cas-server-support-couchbase-authentication/build.gradle +++ /dev/null @@ -1,45 +0,0 @@ -description = "Apereo CAS Couchbase Authentication Support" -ext { - maxParallelForksForTests = 1 - publishMetadata = true - projectMetadata = [ - category: "Authentication", - title: "Couchbase Authentication" - ] -} - -dependencies { - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-authentication-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":support:cas-server-support-person-directory-core") - implementation project(":support:cas-server-support-couchbase-core") - implementation project(":support:cas-server-support-person-directory") - - api project(":api:cas-server-core-api") - - implementation libraries.couchbase - - testImplementation project(":core:cas-server-core") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-logout-api") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-configuration") - - testImplementation project(":core:cas-server-core-services-authentication") - - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-authentication-attributes") - testImplementation project(":core:cas-server-core-notifications") - - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-notifications", configuration: "tests") -} diff --git a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandler.java b/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandler.java deleted file mode 100644 index 611fbfc9ef08..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandler.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.apereo.cas.authentication; - -import org.apereo.cas.authentication.credential.UsernamePasswordCredential; -import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; -import org.apereo.cas.authentication.principal.PrincipalFactory; -import org.apereo.cas.configuration.model.support.couchbase.authentication.CouchbaseAuthenticationProperties; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.services.ServicesManager; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; - -import javax.security.auth.login.AccountNotFoundException; -import javax.security.auth.login.FailedLoginException; -import java.security.GeneralSecurityException; -import java.util.ArrayList; - -/** - * This is {@link CouchbaseAuthenticationHandler}. - * - * @author Misagh Moayyed - * @since 5.2.0 - * @deprecated Since 7.0.0 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchbaseAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler { - private final CouchbaseAuthenticationProperties couchbaseProperties; - - private final CouchbaseClientFactory couchbase; - - public CouchbaseAuthenticationHandler(final ServicesManager servicesManager, - final PrincipalFactory principalFactory, - final CouchbaseClientFactory couchbase, - final CouchbaseAuthenticationProperties couchbaseProperties) { - super(couchbaseProperties.getName(), servicesManager, principalFactory, couchbaseProperties.getOrder()); - this.couchbase = couchbase; - this.couchbaseProperties = couchbaseProperties; - } - - @Override - protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential transformedCredential, - final String originalPassword) - throws GeneralSecurityException { - val query = String.format("%s = '%s'", couchbaseProperties.getUsernameAttribute(), transformedCredential.getUsername()); - val result = couchbase.select(query); - val results = result.rowsAsObject(); - if (results.isEmpty()) { - LOGGER.error("Couchbase query did not return any results/rows."); - throw new AccountNotFoundException("Could not locate account for user " + transformedCredential.getUsername()); - } - - if (results.size() > 1) { - throw new FailedLoginException("More then one row found for user " + transformedCredential.getId()); - } - - val row = results.get(0).getObject(couchbase.getBucket()); - if (!row.containsKey(couchbaseProperties.getPasswordAttribute())) { - throw new FailedLoginException("No password attribute found for " + transformedCredential.getId()); - } - - val entryPassword = row.getString(couchbaseProperties.getPasswordAttribute()); - if (!getPasswordEncoder().matches(originalPassword, entryPassword)) { - LOGGER.warn("Account password on record for [{}] does not match the given/encoded password", transformedCredential.getId()); - throw new FailedLoginException(); - } - - val attributes = CouchbaseClientFactory.collectAttributesFromEntity(row, s -> - !s.equals(couchbaseProperties.getPasswordAttribute()) && !s.equals(couchbaseProperties.getUsernameAttribute())); - val principal = this.principalFactory.createPrincipal(transformedCredential.getId(), attributes); - return createHandlerResult(transformedCredential, principal, new ArrayList<>(0)); - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbaseAuthenticationConfiguration.java b/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbaseAuthenticationConfiguration.java deleted file mode 100644 index b48e8abfa1f9..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbaseAuthenticationConfiguration.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer; -import org.apereo.cas.authentication.AuthenticationHandler; -import org.apereo.cas.authentication.CouchbaseAuthenticationHandler; -import org.apereo.cas.authentication.principal.PrincipalFactory; -import org.apereo.cas.authentication.principal.PrincipalFactoryUtils; -import org.apereo.cas.authentication.principal.PrincipalNameTransformerUtils; -import org.apereo.cas.authentication.principal.PrincipalResolver; -import org.apereo.cas.authentication.support.password.PasswordEncoderUtils; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.couchbase.core.DefaultCouchbaseClientFactory; -import org.apereo.cas.services.ServicesManager; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CouchbaseAuthenticationConfiguration}. - * - * @author Misagh Moayyed - * @author Dmitriy Kopylenko - * @since 5.2.0 - * @deprecated Since 7.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@Slf4j -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Authentication, module = "couchbase") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchbaseAuthenticationConfiguration { - - @ConditionalOnMissingBean(name = "couchbasePrincipalFactory") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public PrincipalFactory couchbasePrincipalFactory() { - return PrincipalFactoryUtils.newPrincipalFactory(); - } - - @ConditionalOnMissingBean(name = "authenticationCouchbaseClientFactory") - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - public CouchbaseClientFactory authenticationCouchbaseClientFactory(final CasConfigurationProperties casProperties) { - val couchbase = casProperties.getAuthn().getCouchbase(); - return new DefaultCouchbaseClientFactory(couchbase); - } - - @ConditionalOnMissingBean(name = "couchbaseAuthenticationHandler") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuthenticationHandler couchbaseAuthenticationHandler( - final CasConfigurationProperties casProperties, - final ConfigurableApplicationContext applicationContext, - @Qualifier("couchbasePrincipalFactory") - final PrincipalFactory couchbasePrincipalFactory, - @Qualifier("authenticationCouchbaseClientFactory") - final CouchbaseClientFactory authenticationCouchbaseClientFactory, - @Qualifier(ServicesManager.BEAN_NAME) - final ServicesManager servicesManager) { - val couchbase = casProperties.getAuthn().getCouchbase(); - val handler = new CouchbaseAuthenticationHandler(servicesManager, couchbasePrincipalFactory, - authenticationCouchbaseClientFactory, couchbase); - handler.setPrincipalNameTransformer(PrincipalNameTransformerUtils.newPrincipalNameTransformer(couchbase.getPrincipalTransformation())); - handler.setPasswordEncoder(PasswordEncoderUtils.newPasswordEncoder(couchbase.getPasswordEncoder(), applicationContext)); - return handler; - } - - @ConditionalOnMissingBean(name = "couchbaseAuthenticationEventExecutionPlanConfigurer") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuthenticationEventExecutionPlanConfigurer couchbaseAuthenticationEventExecutionPlanConfigurer(final CasConfigurationProperties casProperties, - @Qualifier("couchbaseAuthenticationHandler") - final AuthenticationHandler couchbaseAuthenticationHandler, - @Qualifier(PrincipalResolver.BEAN_NAME_PRINCIPAL_RESOLVER) - final PrincipalResolver defaultPrincipalResolver) { - return plan -> { - val couchbase = casProperties.getAuthn().getCouchbase(); - if (StringUtils.isNotBlank(couchbase.getPasswordAttribute()) && StringUtils.isNotBlank(couchbase.getUsernameAttribute())) { - plan.registerAuthenticationHandlerWithPrincipalResolver(couchbaseAuthenticationHandler, defaultPrincipalResolver); - } else { - LOGGER.debug("No couchbase username/password is defined, so couchbase authentication will not be registered in the execution plan"); - } - }; - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbasePersonDirectoryConfiguration.java b/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbasePersonDirectoryConfiguration.java deleted file mode 100644 index 604659b35ca1..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/config/CouchbasePersonDirectoryConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchbase.core.DefaultCouchbaseClientFactory; -import org.apereo.cas.persondir.PersonDirectoryAttributeRepositoryPlanConfigurer; -import org.apereo.cas.persondir.support.CouchbasePersonAttributeDao; -import org.apereo.cas.util.function.FunctionUtils; -import org.apereo.cas.util.spring.beans.BeanCondition; -import org.apereo.cas.util.spring.beans.BeanSupplier; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.apereo.services.persondir.IPersonAttributeDao; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CouchbasePersonDirectoryConfiguration}. - * - * @author Misagh Moayyed - * @author Dmitriy Kopylenko - * @since 5.2.0 - * @deprecated Since 7.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.PersonDirectory, module = "couchbase") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchbasePersonDirectoryConfiguration { - private static final BeanCondition CONDITION = BeanCondition.on("cas.authn.attribute-repository.couchbase.username-attribute"); - - @ConditionalOnMissingBean(name = "couchbasePersonAttributeDao") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public IPersonAttributeDao couchbasePersonAttributeDao( - final ConfigurableApplicationContext applicationContext, - final CasConfigurationProperties casProperties) throws Exception { - return BeanSupplier.of(IPersonAttributeDao.class) - .when(CONDITION.given(applicationContext.getEnvironment())) - .supply(() -> { - val couchbase = casProperties.getAuthn().getAttributeRepository().getCouchbase(); - val cb = new CouchbasePersonAttributeDao(couchbase, new DefaultCouchbaseClientFactory(couchbase)); - cb.setOrder(couchbase.getOrder()); - FunctionUtils.doIfNotNull(couchbase.getId(), cb::setId); - return cb; - }) - .otherwiseProxy() - .get(); - } - - @ConditionalOnMissingBean(name = "couchbaseAttributeRepositoryPlanConfigurer") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public PersonDirectoryAttributeRepositoryPlanConfigurer couchbaseAttributeRepositoryPlanConfigurer( - final ConfigurableApplicationContext applicationContext, - @Qualifier("couchbasePersonAttributeDao") - final IPersonAttributeDao couchbasePersonAttributeDao) throws Exception { - return BeanSupplier.of(PersonDirectoryAttributeRepositoryPlanConfigurer.class) - .when(CONDITION.given(applicationContext.getEnvironment())) - .supply(() -> plan -> plan.registerAttributeRepository(couchbasePersonAttributeDao)) - .otherwiseProxy() - .get(); - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/persondir/support/CouchbasePersonAttributeDao.java b/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/persondir/support/CouchbasePersonAttributeDao.java deleted file mode 100644 index 76c22ea4ffda..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/main/java/org/apereo/cas/persondir/support/CouchbasePersonAttributeDao.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.apereo.cas.persondir.support; - -import org.apereo.cas.configuration.model.support.couchbase.authentication.CouchbasePrincipalAttributesProperties; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.util.CollectionUtils; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apereo.services.persondir.IPersonAttributeDaoFilter; -import org.apereo.services.persondir.IPersonAttributes; -import org.apereo.services.persondir.support.BasePersonAttributeDao; -import org.apereo.services.persondir.support.CaseInsensitiveNamedPersonImpl; -import org.apereo.services.persondir.support.IUsernameAttributeProvider; -import org.apereo.services.persondir.support.SimpleUsernameAttributeProvider; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * This is {@link CouchbasePersonAttributeDao}. - * - * @author Misagh Moayyed - * @since 5.3.0 - * @deprecated Since 7.0.0 - */ -@RequiredArgsConstructor -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchbasePersonAttributeDao extends BasePersonAttributeDao { - private final IUsernameAttributeProvider usernameAttributeProvider = new SimpleUsernameAttributeProvider(); - - private final CouchbasePrincipalAttributesProperties couchbaseProperties; - - private final CouchbaseClientFactory couchbase; - - private static Map> stuffAttributesIntoList(final Map personAttributesMap) { - val entries = (Set>) personAttributesMap.entrySet(); - return entries.stream() - .collect(Collectors.toMap(Map.Entry::getKey, entry -> CollectionUtils.toCollection(entry.getValue(), ArrayList.class))); - } - - @Override - public IPersonAttributes getPerson(final String uid, final Set resolvedPeople, - final IPersonAttributeDaoFilter filter) { - val query = String.format("%s = '%s'", couchbaseProperties.getUsernameAttribute(), uid); - val result = couchbase.select(query); - if (result.rowsAsObject().isEmpty()) { - LOGGER.debug("Couchbase query did not return any results/rows."); - return null; - } - val rows = result.rowsAsObject(); - val attributes = new LinkedHashMap(rows.stream() - .filter(row -> row.containsKey(couchbase.getBucket())) - .map(row -> { - val document = row.getObject(couchbase.getBucket()); - val results = CouchbaseClientFactory.collectAttributesFromEntity(document, s -> true); - return results.entrySet(); - }) - .flatMap(Collection::stream) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); - return new CaseInsensitiveNamedPersonImpl(uid, stuffAttributesIntoList(attributes)); - } - - @Override - public Set getPeople(final Map map, final IPersonAttributeDaoFilter filter, - final Set resolvedPeople) { - return getPeopleWithMultivaluedAttributes(stuffAttributesIntoList(map), filter); - } - - @Override - public Set getPeopleWithMultivaluedAttributes(final Map> map, final IPersonAttributeDaoFilter filter, - final Set resolvedPeople) { - val people = new LinkedHashSet(map.size()); - val username = this.usernameAttributeProvider.getUsernameFromQuery(map); - val person = this.getPerson(username, resolvedPeople, filter); - if (person != null) { - people.add(person); - } - - return people; - } - - @Override - public Set getPossibleUserAttributeNames(final IPersonAttributeDaoFilter filter) { - return new LinkedHashSet<>(0); - } - - @Override - public Set getAvailableQueryAttributes(final IPersonAttributeDaoFilter filter) { - return new LinkedHashSet<>(0); - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-couchbase-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 08d48f9832a0..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,2 +0,0 @@ -org.apereo.cas.config.CouchbaseAuthenticationConfiguration -org.apereo.cas.config.CouchbasePersonDirectoryConfiguration diff --git a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AbstractCouchbaseTests.java b/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AbstractCouchbaseTests.java deleted file mode 100644 index bfa8c3b7ad46..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AbstractCouchbaseTests.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.apereo.cas; - -import org.apereo.cas.config.CasAuthenticationEventExecutionPlanTestConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationPrincipalConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationServiceSelectionStrategyConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationSupportConfiguration; -import org.apereo.cas.config.CasCoreConfiguration; -import org.apereo.cas.config.CasCoreHttpConfiguration; -import org.apereo.cas.config.CasCoreNotificationsConfiguration; -import org.apereo.cas.config.CasCoreServicesConfiguration; -import org.apereo.cas.config.CasCoreTicketCatalogConfiguration; -import org.apereo.cas.config.CasCoreTicketIdGeneratorsConfiguration; -import org.apereo.cas.config.CasCoreTicketsConfiguration; -import org.apereo.cas.config.CasCoreTicketsSerializationConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasDefaultServiceTicketIdGeneratorsConfiguration; -import org.apereo.cas.config.CasPersonDirectoryConfiguration; -import org.apereo.cas.config.CasRegisteredServicesTestConfiguration; -import org.apereo.cas.config.CouchbaseAuthenticationConfiguration; -import org.apereo.cas.config.CouchbasePersonDirectoryConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.logout.config.CasCoreLogoutConfiguration; - -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration; -import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.context.annotation.Import; - -/** - * This is {@link AbstractCouchbaseTests}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7.0.0 - */ -@Deprecated(since = "7.0.0") -public abstract class AbstractCouchbaseTests { - @ImportAutoConfiguration({ - RefreshAutoConfiguration.class, - MailSenderAutoConfiguration.class, - AopAutoConfiguration.class - }) - @SpringBootConfiguration - @Import({ - CouchbaseAuthenticationConfiguration.class, - CouchbasePersonDirectoryConfiguration.class, - CasCoreConfiguration.class, - CasCoreTicketsConfiguration.class, - CasCoreLogoutConfiguration.class, - CasCoreServicesConfiguration.class, - CasCoreTicketIdGeneratorsConfiguration.class, - CasCoreTicketsSerializationConfiguration.class, - CasCoreTicketCatalogConfiguration.class, - CasCoreAuthenticationConfiguration.class, - CasCoreAuthenticationSupportConfiguration.class, - CasCoreAuthenticationServiceSelectionStrategyConfiguration.class, - CasCoreHttpConfiguration.class, - CasCoreNotificationsConfiguration.class, - CasCoreWebConfiguration.class, - CasPersonDirectoryConfiguration.class, - CasCoreUtilConfiguration.class, - CasRegisteredServicesTestConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - CasAuthenticationEventExecutionPlanTestConfiguration.class, - CasDefaultServiceTicketIdGeneratorsConfiguration.class, - CasCoreAuthenticationPrincipalConfiguration.class - }) - public static class SharedTestConfiguration { - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AllTestsSuite.java b/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AllTestsSuite.java deleted file mode 100644 index ced1c5c00bf0..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/AllTestsSuite.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.apereo.cas; - -import org.apereo.cas.authentication.CouchbaseAuthenticationHandlerTests; -import org.apereo.cas.authentication.CouchbasePersonAttributeDaoTests; -import org.apereo.cas.config.CouchbaseConfigurationTests; - -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; - -/** - * This is {@link AllTestsSuite}. - * - * @author Misagh Moayyed - * @since 6.0.0-RC3 - */ -@SelectClasses({ - CouchbaseConfigurationTests.class, - CouchbasePersonAttributeDaoTests.class, - CouchbaseAuthenticationHandlerTests.class -}) -@Suite -public class AllTestsSuite { -} diff --git a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandlerTests.java b/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandlerTests.java deleted file mode 100644 index 8d595d03383a..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbaseAuthenticationHandlerTests.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.apereo.cas.authentication; - -import org.apereo.cas.authentication.principal.PrincipalFactoryUtils; -import org.apereo.cas.authentication.principal.Service; -import org.apereo.cas.authentication.support.password.PasswordEncoderUtils; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.model.core.authentication.PasswordEncoderProperties; -import org.apereo.cas.couchbase.core.DefaultCouchbaseClientFactory; -import org.apereo.cas.services.ServicesManager; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.val; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.context.support.StaticApplicationContext; - -import javax.security.auth.login.AccountNotFoundException; -import javax.security.auth.login.FailedLoginException; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * Basic unit tests on the {@link CouchbaseAuthenticationHandler} to ensure the password check behavior. - * - * @author Jerome LELEU - * @since 6.0.4 - * @deprecated Since 7.0.0 - */ -@Tag("Couchbase") -@EnabledIfListeningOnPort(port = 8091) -@SpringBootTest(classes = RefreshAutoConfiguration.class, - properties = { - "cas.authn.couchbase.cluster-username=admin", - "cas.authn.couchbase.cluster-password=password", - "cas.authn.couchbase.bucket=pplbucket" - }) -@EnableConfigurationProperties(CasConfigurationProperties.class) -@Deprecated(since = "7.0.0") -public class CouchbaseAuthenticationHandlerTests { - @Autowired - private CasConfigurationProperties casProperties; - - @Test - public void verify() throws Exception { - val props = casProperties.getAuthn().getCouchbase(); - val factory = new DefaultCouchbaseClientFactory(props); - val handler = new CouchbaseAuthenticationHandler(mock(ServicesManager.class), - PrincipalFactoryUtils.newPrincipalFactory(), factory, props); - val c = CoreAuthenticationTestUtils.getCredentialsWithDifferentUsernameAndPassword("casuser", "Mellon"); - val result = handler.authenticate(c, mock(Service.class)); - assertNotNull(result); - val attributes = result.getPrincipal().getAttributes(); - assertEquals(2, attributes.size()); - assertTrue(attributes.containsKey("firstname")); - assertTrue(attributes.containsKey("lastname")); - } - - @Test - public void verifyBadEncoding() { - val ctx = new StaticApplicationContext(); - ctx.refresh(); - - val props = casProperties.getAuthn().getCouchbase(); - val factory = new DefaultCouchbaseClientFactory(props); - val handler = new CouchbaseAuthenticationHandler(mock(ServicesManager.class), - PrincipalFactoryUtils.newPrincipalFactory(), factory, props); - handler.setPasswordEncoder(PasswordEncoderUtils.newPasswordEncoder(new PasswordEncoderProperties().setType("SCRYPT"), ctx)); - val c = CoreAuthenticationTestUtils.getCredentialsWithDifferentUsernameAndPassword("casuser", "Mellon"); - assertThrows(FailedLoginException.class, () -> handler.authenticate(c, mock(Service.class))); - } - - @Test - public void verifyBadRecord() { - val ctx = new StaticApplicationContext(); - ctx.refresh(); - val props = casProperties.getAuthn().getCouchbase(); - val factory = new DefaultCouchbaseClientFactory(props); - val handler = new CouchbaseAuthenticationHandler(mock(ServicesManager.class), - PrincipalFactoryUtils.newPrincipalFactory(), factory, props); - handler.setPasswordEncoder(PasswordEncoderUtils.newPasswordEncoder(new PasswordEncoderProperties().setType("SCRYPT"), ctx)); - val c = CoreAuthenticationTestUtils.getCredentialsWithDifferentUsernameAndPassword("nopsw", "Mellon"); - assertThrows(FailedLoginException.class, () -> handler.authenticate(c, mock(Service.class))); - } - - @Test - public void verifyMissingUser() { - val props = casProperties.getAuthn().getCouchbase(); - val factory = new DefaultCouchbaseClientFactory(props); - val handler = new CouchbaseAuthenticationHandler(mock(ServicesManager.class), - PrincipalFactoryUtils.newPrincipalFactory(), factory, props); - val c = CoreAuthenticationTestUtils.getCredentialsWithDifferentUsernameAndPassword("casuser-missing", "Mellon"); - assertThrows(AccountNotFoundException.class, () -> handler.authenticate(c, mock(Service.class))); - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbasePersonAttributeDaoTests.java b/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbasePersonAttributeDaoTests.java deleted file mode 100644 index e1323bdceb7a..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/authentication/CouchbasePersonAttributeDaoTests.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.apereo.cas.authentication; - -import org.apereo.cas.AbstractCouchbaseTests; -import org.apereo.cas.authentication.principal.PrincipalResolver; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.val; -import org.apereo.services.persondir.IPersonAttributeDao; -import org.apereo.services.persondir.IPersonAttributeDaoFilter; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.SpringBootTest; - -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchbasePersonAttributeDaoTests}. - * - * @author Misagh Moayyed - * @since 5.3.0 - * @deprecated Since 7.0.0 - */ -@Tag("Couchbase") -@EnabledIfListeningOnPort(port = 8091) -@SpringBootTest(classes = AbstractCouchbaseTests.SharedTestConfiguration.class, - properties = { - "cas.authn.couchbase.cluster-username=admin", - "cas.authn.couchbase.cluster-password=password", - "cas.authn.couchbase.bucket=pplbucket", - - "cas.authn.attribute-repository.couchbase.cluster-password=password", - "cas.authn.attribute-repository.couchbase.cluster-username=admin", - "cas.authn.attribute-repository.couchbase.bucket=pplbucket", - "cas.authn.attribute-repository.couchbase.username-attribute=username" - }) -@EnableConfigurationProperties(CasConfigurationProperties.class) -@Deprecated(since = "7.0.0") -public class CouchbasePersonAttributeDaoTests { - @Autowired - @Qualifier(PrincipalResolver.BEAN_NAME_ATTRIBUTE_REPOSITORY) - private IPersonAttributeDao attributeRepository; - - @Test - public void verifyAttributes() { - val person = attributeRepository.getPerson("casuser"); - assertNotNull(person); - val attributes = person.getAttributes(); - assertTrue(attributes.containsKey("firstname")); - assertTrue(attributes.containsKey("lastname")); - assertEquals("casuser", person.getName()); - } - - @Test - public void verifyUnknown() { - val person = attributeRepository.getPerson("unknown"); - assertNull(person); - - val persons = attributeRepository.getPeople(Map.of("username", "casuser"), IPersonAttributeDaoFilter.alwaysChoose()); - assertFalse(persons.isEmpty()); - - assertTrue(attributeRepository.getPossibleUserAttributeNames(IPersonAttributeDaoFilter.alwaysChoose()).isEmpty()); - assertTrue(attributeRepository.getAvailableQueryAttributes(IPersonAttributeDaoFilter.alwaysChoose()).isEmpty()); - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/config/CouchbaseConfigurationTests.java b/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/config/CouchbaseConfigurationTests.java deleted file mode 100644 index e62fcd95e742..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/test/java/org/apereo/cas/config/CouchbaseConfigurationTests.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.AbstractCouchbaseTests; -import org.apereo.cas.authentication.AuthenticationHandler; -import org.apereo.cas.persondir.PersonDirectoryAttributeRepositoryPlanConfigurer; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchbaseConfigurationTests}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7.0.0 - */ -@Tag("Couchbase") -@EnabledIfListeningOnPort(port = 8091) -@SpringBootTest(classes = AbstractCouchbaseTests.SharedTestConfiguration.class, - properties = { - "cas.authn.couchbase.cluster-username=admin", - "cas.authn.couchbase.cluster-password=password", - "cas.authn.couchbase.bucket=testbucket", - - "cas.authn.attribute-repository.couchbase.cluster-password=password", - "cas.authn.attribute-repository.couchbase.cluster-username=admin", - "cas.authn.attribute-repository.couchbase.bucket=testbucket", - "cas.authn.attribute-repository.couchbase.username-attribute=username" - }) -@Deprecated(since = "7.0.0") -public class CouchbaseConfigurationTests { - @Autowired - @Qualifier("couchbaseAttributeRepositoryPlanConfigurer") - private PersonDirectoryAttributeRepositoryPlanConfigurer couchbaseAttributeRepositoryPlanConfigurer; - - @Autowired - @Qualifier("couchbaseAuthenticationHandler") - private AuthenticationHandler couchbaseAuthenticationHandler; - - @Test - public void verifyOperation() { - assertNotNull(couchbaseAttributeRepositoryPlanConfigurer); - assertNotNull(couchbaseAuthenticationHandler); - } -} diff --git a/support/cas-server-support-couchbase-authentication/src/test/resources/couchbase-authn.properties b/support/cas-server-support-couchbase-authentication/src/test/resources/couchbase-authn.properties deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/support/cas-server-support-couchbase-authentication/src/test/resources/log4j2-test.xml b/support/cas-server-support-couchbase-authentication/src/test/resources/log4j2-test.xml deleted file mode 100644 index 29d9d388fd77..000000000000 --- a/support/cas-server-support-couchbase-authentication/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-couchbase-core/build.gradle b/support/cas-server-support-couchbase-core/build.gradle deleted file mode 100644 index 179c71386107..000000000000 --- a/support/cas-server-support-couchbase-core/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -description = "Apereo CAS Couchbase Support Core" -dependencies { - api libraries.couchbase - implementation project(":core:cas-server-core-util-api") - - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") -} diff --git a/support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/CouchbaseClientFactory.java b/support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/CouchbaseClientFactory.java deleted file mode 100644 index 678771189b35..000000000000 --- a/support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/CouchbaseClientFactory.java +++ /dev/null @@ -1,255 +0,0 @@ -package org.apereo.cas.couchbase.core; - -import org.apereo.cas.util.CollectionUtils; - -import com.couchbase.client.java.Cluster; -import com.couchbase.client.java.json.JsonObject; -import com.couchbase.client.java.kv.GetOptions; -import com.couchbase.client.java.kv.GetResult; -import com.couchbase.client.java.kv.MutationResult; -import com.couchbase.client.java.kv.UpsertOptions; -import com.couchbase.client.java.query.QueryOptions; -import com.couchbase.client.java.query.QueryResult; -import org.apache.commons.lang3.tuple.Pair; - -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * A factory class which produces a client for a particular Couchbase getBucket. - * A design consideration was that we want the server to start even if Couchbase - * is unavailable, picking up the connection when Couchbase comes online. Hence - * the creation of the client is made using a scheduled task which is repeated - * until successful connection is made. - * - * @author Fredrik Jönsson "fjo@kth.se" - * @author Misagh Moayyed - * @since 4.2 - * @deprecated Since 7.0.0 - */ -@Deprecated(since = "7.0.0") -public interface CouchbaseClientFactory { - - /** - * Collect attributes from entity map. - * - * @param couchbaseEntity the couchbase entity - * @param filter the filter - * @return the map - */ - static Map> collectAttributesFromEntity(final JsonObject couchbaseEntity, - final Predicate filter) { - return couchbaseEntity.getNames() - .stream() - .filter(filter) - .map(name -> Pair.of(name, couchbaseEntity.get(name))) - .collect(Collectors.toMap(Pair::getKey, s -> CollectionUtils.wrapList(s.getValue()))); - } - - /** - * Shutdown. - */ - void shutdown(); - - /** - * Gets connection timeout. - * - * @return the connection timeout - */ - Duration getConnectionTimeout(); - - /** - * Gets idle connection timeout. - * - * @return the idle connection timeout - */ - Duration getIdleConnectionTimeout(); - - /** - * Gets search timeout. - * - * @return the search timeout - */ - Duration getSearchTimeout(); - - /** - * Gets query timeout. - * - * @return the query timeout - */ - Duration getQueryTimeout(); - - /** - * Gets view timeout. - * - * @return the view timeout - */ - Duration getViewTimeout(); - - /** - * Gets kv timeout. - * - * @return the kv timeout - */ - Duration getKvTimeout(); - - /** - * Count long. - * - * @param query the query - * @return the long - */ - long count(String query); - - /** - * Count long. - * - * @param query the query - * @param parameters the parameters - * @return the long - */ - long count(String query, Optional parameters); - - /** - * Select query result. - * - * @param query the query - * @param parameters the parameters - * @return the query result - */ - QueryResult select(String query, Optional parameters); - - /** - * Select query result. - * - * @param query the query - * @param options the options - * @return the query result - */ - QueryResult select(String query, QueryOptions options); - - /** - * Select query result. - * - * @param query the query - * @param options the options - * @param includeResultsInBucket the include results in bucket - * @return the query result - */ - QueryResult select(String query, - QueryOptions options, - boolean includeResultsInBucket); - - /** - * Select query result. - * - * @param statement the statement - * @return the query result - */ - QueryResult select(String statement); - - /** - * Remove query result. - * - * @param query the query - * @param parameters the parameters - * @return the query result - */ - QueryResult remove(String query, Optional parameters); - - /** - * Remove query result. - * - * @param query the query - * @return the query result - */ - QueryResult remove(String query); - - /** - * Remove all query result. - * - * @return the query result - */ - QueryResult removeAll(); - - /** - * Bucket upsert default collection mutation result. - * - * @param content the content - * @return the mutation result - */ - MutationResult bucketUpsertDefaultCollection(String content); - - /** - * Bucket upsert default collection mutation result. - * - * @param id the id - * @param document the document - * @return the mutation result - */ - MutationResult bucketUpsertDefaultCollection(String id, Object document); - - /** - * Bucket upsert default collection mutation result. - * - * @param id the id - * @param document the document - * @param options the options - * @return the mutation result - */ - MutationResult bucketUpsertDefaultCollection(String id, Object document, - UpsertOptions options); - - /** - * Bucket remove from default collection optional. - * - * @param id the id - * @return the optional - */ - Optional bucketRemoveFromDefaultCollection(String id); - - /** - * Gets bucket. - * - * @return the bucket - */ - String getBucket(); - - /** - * Bucket get get result. - * - * @param id the id - * @return the get result - */ - GetResult bucketGet(String id); - - /** - * Bucket get get result. - * - * @param id the id - * @param options the options - * @return the get result - */ - GetResult bucketGet(String id, GetOptions options); - - /** - * Execute query query result. - * - * @param options the options - * @param formattedQuery the formatted query - * @return the query result - */ - QueryResult executeQuery(QueryOptions options, - String formattedQuery); - - /** - * Gets cluster. - * - * @return the cluster - */ - Cluster getCluster(); -} diff --git a/support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/DefaultCouchbaseClientFactory.java b/support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/DefaultCouchbaseClientFactory.java deleted file mode 100644 index 7c63be1334ce..000000000000 --- a/support/cas-server-support-couchbase-core/src/main/java/org/apereo/cas/couchbase/core/DefaultCouchbaseClientFactory.java +++ /dev/null @@ -1,263 +0,0 @@ -package org.apereo.cas.couchbase.core; - -import org.apereo.cas.configuration.model.support.couchbase.BaseCouchbaseProperties; -import org.apereo.cas.configuration.support.Beans; -import org.apereo.cas.util.LoggingUtils; - -import com.couchbase.client.core.env.IoConfig; -import com.couchbase.client.core.env.NetworkResolution; -import com.couchbase.client.core.env.SeedNode; -import com.couchbase.client.core.env.TimeoutConfig; -import com.couchbase.client.core.error.DocumentNotFoundException; -import com.couchbase.client.java.Cluster; -import com.couchbase.client.java.ClusterOptions; -import com.couchbase.client.java.env.ClusterEnvironment; -import com.couchbase.client.java.json.JsonObject; -import com.couchbase.client.java.kv.GetOptions; -import com.couchbase.client.java.kv.GetResult; -import com.couchbase.client.java.kv.MutationResult; -import com.couchbase.client.java.kv.UpsertOptions; -import com.couchbase.client.java.query.QueryOptions; -import com.couchbase.client.java.query.QueryResult; -import com.couchbase.client.java.query.QueryScanConsistency; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apache.commons.lang3.StringUtils; - -import java.time.Duration; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; - -/** - * A factory class which produces a client for a particular Couchbase getBucket. - * A design consideration was that we want the server to start even if Couchbase - * is unavailable, picking up the connection when Couchbase comes online. Hence - * the creation of the client is made using a scheduled task which is repeated - * until successful connection is made. - * - * @author Fredrik Jönsson "fjo@kth.se" - * @author Misagh Moayyed - * @since 4.2 - * @deprecated Since 7.0.0 - */ -@Slf4j -@Getter -@Deprecated(since = "7.0.0") -public class DefaultCouchbaseClientFactory implements CouchbaseClientFactory { - private final BaseCouchbaseProperties properties; - - private Cluster cluster; - - /** - * Instantiates a new Couchbase client factory. - * - * @param properties the properties - */ - public DefaultCouchbaseClientFactory(final BaseCouchbaseProperties properties) { - this.properties = properties; - initializeCluster(); - } - - /** - * Inverse of connectBucket, shuts down the client, cancelling connection - * task if not completed. - */ - @Override - public void shutdown() { - if (this.cluster != null) { - LOGGER.debug("Disconnecting from Couchbase cluster"); - this.cluster.disconnect(); - } - } - - @Override - public Duration getConnectionTimeout() { - return Beans.newDuration(properties.getConnectionTimeout()); - } - - @Override - public Duration getIdleConnectionTimeout() { - return Beans.newDuration(properties.getIdleConnectionTimeout()); - } - - @Override - public Duration getSearchTimeout() { - return Beans.newDuration(properties.getSearchTimeout()); - } - - @Override - public Duration getQueryTimeout() { - return Beans.newDuration(properties.getQueryTimeout()); - } - - @Override - public Duration getViewTimeout() { - return Beans.newDuration(properties.getViewTimeout()); - } - - @Override - public Duration getKvTimeout() { - return Beans.newDuration(properties.getKvTimeout()); - } - - @Override - public long count(final String query) { - return count(query, Optional.empty()); - } - - @Override - public long count(final String query, final Optional parameters) { - val formattedQuery = String.format("SELECT count(*) as count FROM `%s` WHERE %s", properties.getBucket(), query); - val options = QueryOptions.queryOptions() - .readonly(true) - .scanConsistency(QueryScanConsistency.valueOf(properties.getScanConsistency())); - parameters.ifPresent(options::parameters); - val result = executeQuery(options, formattedQuery); - return result.rowsAsObject().get(0).getLong("count"); - } - - @Override - public QueryResult select(final String query, final Optional parameters) { - val formattedQuery = String.format("SELECT * FROM `%s` WHERE %s", properties.getBucket(), query); - val options = QueryOptions.queryOptions().scanConsistency(QueryScanConsistency.valueOf(properties.getScanConsistency())); - parameters.ifPresent(options::parameters); - return executeQuery(options, formattedQuery); - } - - @Override - public QueryResult select(final String query, final QueryOptions options) { - return select(query, options, true); - } - - @Override - public QueryResult select(final String query, - final QueryOptions options, - final boolean includeResultsInBucket) { - val formattedQuery = String.format("SELECT %s* FROM `%s` WHERE %s", - includeResultsInBucket ? StringUtils.EMPTY : properties.getBucket() + '.', - properties.getBucket(), query); - return executeQuery(options, formattedQuery); - } - - @Override - public QueryResult select(final String statement) { - return select(statement, Optional.empty()); - } - - @Override - public QueryResult remove(final String query, final Optional parameters) { - val formattedQuery = String.format("DELETE FROM `%s` WHERE %s", properties.getBucket(), query); - val options = QueryOptions.queryOptions() - .scanConsistency(QueryScanConsistency.valueOf(properties.getScanConsistency())); - parameters.ifPresent(options::parameters); - return executeQuery(options, formattedQuery); - } - - @Override - public QueryResult remove(final String query) { - return remove(query, Optional.empty()); - } - - @Override - public QueryResult removeAll() { - return remove("1=1", Optional.empty()); - } - - @Override - public MutationResult bucketUpsertDefaultCollection(final String content) { - val id = UUID.randomUUID().toString(); - val document = JsonObject.fromJson(content); - return bucketUpsertDefaultCollection(id, document); - } - - @Override - public MutationResult bucketUpsertDefaultCollection(final String id, final Object document) { - return bucketUpsertDefaultCollection(id, document, UpsertOptions.upsertOptions()); - } - - @Override - public MutationResult bucketUpsertDefaultCollection(final String id, final Object document, - final UpsertOptions options) { - val bucket = this.cluster.bucket(properties.getBucket()); - return bucket.defaultCollection().upsert(id, document, options); - } - - @Override - public Optional bucketRemoveFromDefaultCollection(final String id) { - val bucket = this.cluster.bucket(properties.getBucket()); - try { - return Optional.of(bucket.defaultCollection().remove(id)); - } catch (final DocumentNotFoundException e) { - LOGGER.trace(e.getMessage(), e); - } - return Optional.empty(); - } - - @Override - public String getBucket() { - return properties.getBucket(); - } - - @Override - public GetResult bucketGet(final String id) { - return bucketGet(id, GetOptions.getOptions()); - } - - @Override - public GetResult bucketGet(final String id, final GetOptions options) { - try { - val bucket = cluster.bucket(properties.getBucket()); - return bucket.defaultCollection().get(id, options); - } catch (final DocumentNotFoundException e) { - LoggingUtils.warn(LOGGER, e); - } - return null; - } - - private void initializeCluster() { - shutdown(); - LOGGER.debug("Initializing Couchbase cluster for nodes [{}]", properties.getAddresses()); - - val env = ClusterEnvironment - .builder() - .maxNumRequestsInRetry(properties.getMaxNumRequestsInRetry()) - .timeoutConfig(TimeoutConfig - .connectTimeout(getConnectionTimeout()) - .kvTimeout(getKvTimeout()) - .queryTimeout(getQueryTimeout()) - .searchTimeout(getSearchTimeout()) - .viewTimeout(getViewTimeout())) - .ioConfig(IoConfig - .idleHttpConnectionTimeout(getIdleConnectionTimeout()) - .maxHttpConnections(properties.getMaxHttpConnections()) - .networkResolution(NetworkResolution.AUTO)) - .build(); - - val listOfNodes = properties.getAddresses() - .stream() - .map(SeedNode::create) - .collect(Collectors.toSet()); - - val options = ClusterOptions - .clusterOptions(properties.getClusterUsername(), properties.getClusterPassword()) - .environment(env); - this.cluster = Cluster.connect(listOfNodes, options); - } - - @Override - public QueryResult executeQuery(final QueryOptions options, - final String formattedQuery) { - LOGGER.trace("Executing query [{}]", formattedQuery); - options - .scanConsistency(QueryScanConsistency.valueOf(properties.getScanConsistency())) - .timeout(getConnectionTimeout()) - .scanWait(Beans.newDuration(properties.getScanWaitTimeout())); - if (properties.getMaxParallelism() > 0) { - options.maxParallelism(properties.getMaxParallelism()); - } - return cluster.query(formattedQuery, options); - } -} - diff --git a/support/cas-server-support-couchbase-core/src/test/java/org/apereo/cas/couchbase/core/CouchbaseClientFactoryTests.java b/support/cas-server-support-couchbase-core/src/test/java/org/apereo/cas/couchbase/core/CouchbaseClientFactoryTests.java deleted file mode 100644 index 183c92db5817..000000000000 --- a/support/cas-server-support-couchbase-core/src/test/java/org/apereo/cas/couchbase/core/CouchbaseClientFactoryTests.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.apereo.cas.couchbase.core; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import com.couchbase.client.java.query.QueryOptions; -import lombok.val; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchbaseClientFactoryTests}. - * - * @author Misagh Moayyed - * @since 6.2.0 - * @deprecated Since 7.0.0 - */ -@Tag("Couchbase") -@EnabledIfListeningOnPort(port = 8091) -@SpringBootTest(classes = RefreshAutoConfiguration.class, - properties = { - "cas.authn.couchbase.cluster-username=admin", - "cas.authn.couchbase.cluster-password=password", - "cas.authn.couchbase.max-parallelism=1", - "cas.authn.couchbase.bucket=testbucket" - }) -@EnableConfigurationProperties(CasConfigurationProperties.class) -@Deprecated(since = "7.0.0") -public class CouchbaseClientFactoryTests { - @Autowired - private CasConfigurationProperties casProperties; - - @Test - public void verifyInit() { - val factory = new DefaultCouchbaseClientFactory(casProperties.getAuthn().getCouchbase()); - assertNotNull(factory.getConnectionTimeout()); - assertNotNull(factory.getKvTimeout()); - assertNotNull(factory.getProperties()); - assertNotNull(factory.getQueryTimeout()); - assertNotNull(factory.getSearchTimeout()); - assertNotNull(factory.getViewTimeout()); - assertNotNull(factory.getCluster()); - - assertNotNull(factory.select("1=1", QueryOptions.queryOptions())); - assertNotNull(factory.removeAll()); - - assertDoesNotThrow(factory::shutdown); - - } -} diff --git a/support/cas-server-support-couchbase-service-registry/build.gradle b/support/cas-server-support-couchbase-service-registry/build.gradle deleted file mode 100644 index edaa3b2bd5f2..000000000000 --- a/support/cas-server-support-couchbase-service-registry/build.gradle +++ /dev/null @@ -1,36 +0,0 @@ -description = "Apereo CAS Couchbase Service Registry" - -ext { - maxParallelForksForTests = 1 - publishMetadata = true - projectMetadata = [ - category: "Service Registries", - title: "Couchbase Service Registry" - ] -} - -dependencies { - api project(":api:cas-server-core-api-services") - - api libraries.couchbase - - implementation project(":core:cas-server-core-services") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":core:cas-server-core-services-registry") - implementation project(":core:cas-server-core-services-api") - implementation project(":support:cas-server-support-couchbase-core") - - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-notifications") - testImplementation project(":support:cas-server-support-oauth-services") - testImplementation project(":support:cas-server-support-saml-idp-core") - testImplementation project(":support:cas-server-support-oidc-services") - testImplementation project(":support:cas-server-support-ws-idp-api") - - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-notifications", configuration: "tests") -} diff --git a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/config/CouchbaseServiceRegistryConfiguration.java b/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/config/CouchbaseServiceRegistryConfiguration.java deleted file mode 100644 index fa8cdc95e964..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/config/CouchbaseServiceRegistryConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.couchbase.core.DefaultCouchbaseClientFactory; -import org.apereo.cas.services.CouchbaseServiceRegistry; -import org.apereo.cas.services.ServiceRegistry; -import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer; -import org.apereo.cas.services.ServiceRegistryListener; -import org.apereo.cas.services.util.RegisteredServiceJsonSerializer; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * This is {@link CouchbaseServiceRegistryConfiguration}. - * - * @author Misagh Moayyed - * @since 5.0.0 - * @deprecated Since 7.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.ServiceRegistry, module = "couchbase") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchbaseServiceRegistryConfiguration { - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - @ConditionalOnMissingBean(name = "serviceRegistryCouchbaseClientFactory") - public CouchbaseClientFactory serviceRegistryCouchbaseClientFactory(final CasConfigurationProperties casProperties) { - val couchbase = casProperties.getServiceRegistry().getCouchbase(); - return new DefaultCouchbaseClientFactory(couchbase); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "couchbaseServiceRegistry") - public ServiceRegistry couchbaseServiceRegistry( - final ConfigurableApplicationContext applicationContext, - final ObjectProvider> serviceRegistryListeners, - @Qualifier("serviceRegistryCouchbaseClientFactory") - final CouchbaseClientFactory serviceRegistryCouchbaseClientFactory) { - return new CouchbaseServiceRegistry(applicationContext, serviceRegistryCouchbaseClientFactory, - new RegisteredServiceJsonSerializer(applicationContext), - Optional.ofNullable(serviceRegistryListeners.getIfAvailable()).orElseGet(ArrayList::new)); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "couchbaseServiceRegistryExecutionPlanConfigurer") - public ServiceRegistryExecutionPlanConfigurer couchbaseServiceRegistryExecutionPlanConfigurer( - @Qualifier("couchbaseServiceRegistry") - final ServiceRegistry couchbaseServiceRegistry) { - return plan -> plan.registerServiceRegistry(couchbaseServiceRegistry); - } -} diff --git a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceDeletedEvent.java b/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceDeletedEvent.java deleted file mode 100644 index 5502464a217b..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceDeletedEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apereo.cas.services; - -import org.springframework.context.ApplicationEvent; - -import java.io.Serial; - -/** - * This is {@link CouchbaseRegisteredServiceDeletedEvent}. - * - * @author Misagh Moayyed - * @since 6.0.0 - * @deprecated Since 7.0.0 - */ -@Deprecated(since = "7.0.0") -public class CouchbaseRegisteredServiceDeletedEvent extends ApplicationEvent { - @Serial - private static final long serialVersionUID = -6926761736041237960L; - - public CouchbaseRegisteredServiceDeletedEvent(final Object source) { - super(source); - } -} diff --git a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceSavedEvent.java b/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceSavedEvent.java deleted file mode 100644 index 514290e14425..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseRegisteredServiceSavedEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apereo.cas.services; - -import org.springframework.context.ApplicationEvent; - -import java.io.Serial; - -/** - * This is {@link CouchbaseRegisteredServiceSavedEvent}. - * - * @author Misagh Moayyed - * @since 6.0.0 - * @deprecated Since 7.0.0 - */ -@Deprecated(since = "7.0.0") -public class CouchbaseRegisteredServiceSavedEvent extends ApplicationEvent { - @Serial - private static final long serialVersionUID = 5538958334155906185L; - - public CouchbaseRegisteredServiceSavedEvent(final Object source) { - super(source); - } -} diff --git a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseServiceRegistry.java b/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseServiceRegistry.java deleted file mode 100644 index d4eebb78e8f1..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/main/java/org/apereo/cas/services/CouchbaseServiceRegistry.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.apereo.cas.services; - -import org.apereo.cas.couchbase.core.CouchbaseClientFactory; -import org.apereo.cas.support.events.service.CasRegisteredServiceLoadedEvent; -import org.apereo.cas.util.serialization.StringSerializer; - -import com.couchbase.client.core.error.DocumentNotFoundException; -import com.couchbase.client.java.query.QueryResult; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apereo.inspektr.common.web.ClientInfoHolder; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.context.ConfigurableApplicationContext; - -import java.io.StringReader; -import java.io.StringWriter; -import java.util.Collection; -import java.util.Objects; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.UUID; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -/** - * This is {@link CouchbaseServiceRegistry}. - * A Service Registry storage backend which uses the memcached protocol. - * CouchBase is a multi host NoSQL database with a memcached interface to persistent - * storage which also is quite usable as a replicated ticket storage - * engine for multiple front end CAS servers. - * - * @author Fredrik Jönsson "fjo@kth.se" - * @author Misagh Moayyed - * @since 4.2.0 - * @deprecated Since 7.0.0 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchbaseServiceRegistry extends AbstractServiceRegistry implements DisposableBean { - private final CouchbaseClientFactory couchbase; - - private final StringSerializer registeredServiceJsonSerializer; - - public CouchbaseServiceRegistry(final ConfigurableApplicationContext applicationContext, - final CouchbaseClientFactory couchbase, - final StringSerializer registeredServiceJsonSerializer, - final Collection serviceRegistryListeners) { - super(applicationContext, serviceRegistryListeners); - this.couchbase = couchbase; - this.registeredServiceJsonSerializer = registeredServiceJsonSerializer; - } - - @Override - public RegisteredService save(final RegisteredService service) { - LOGGER.trace("Saving service [{}]:[{}]", service.getClass().getName(), service.getName()); - if (service.getId() == RegisteredService.INITIAL_IDENTIFIER_VALUE) { - service.setId(UUID.randomUUID().getLeastSignificantBits()); - } - val stringWriter = new StringWriter(); - this.registeredServiceJsonSerializer.to(stringWriter, service); - invokeServiceRegistryListenerPreSave(service); - couchbase.bucketUpsertDefaultCollection(String.valueOf(service.getId()), stringWriter.toString()); - LOGGER.debug("Saved service [{}] as [{}]", service.getName(), service.getName()); - publishEvent(new CouchbaseRegisteredServiceSavedEvent(this)); - return service; - } - - @Override - public boolean delete(final RegisteredService service) { - LOGGER.trace("Deleting service [{}]", service.getName()); - this.couchbase.bucketRemoveFromDefaultCollection(String.valueOf(service.getId())); - publishEvent(new CouchbaseRegisteredServiceDeletedEvent(this)); - return true; - } - - @Override - public void deleteAll() { - this.couchbase.removeAll(); - } - - @Override - public Collection load() { - val allServices = queryForAllServices().rowsAsObject(); - val spliterator = Spliterators.spliteratorUnknownSize(allServices.iterator(), Spliterator.ORDERED); - val clientInfo = ClientInfoHolder.getClientInfo(); - - return StreamSupport.stream(spliterator, false) - .filter(document -> document.containsKey(couchbase.getBucket())) - .map(document -> { - val json = document.getString(couchbase.getBucket()); - LOGGER.trace("Found service: [{}]", json); - return this.registeredServiceJsonSerializer.from(json); - }) - .filter(Objects::nonNull) - .map(this::invokeServiceRegistryListenerPostLoad) - .filter(Objects::nonNull) - .peek(service -> publishEvent(new CasRegisteredServiceLoadedEvent(this, service, clientInfo))) - .collect(Collectors.toList()); - } - - @Override - public RegisteredService findServiceById(final long id) { - try { - val document = couchbase.bucketGet(String.valueOf(id)); - if (document != null) { - val json = document.contentAs(String.class); - try (val stringReader = new StringReader(json)) { - return registeredServiceJsonSerializer.from(stringReader); - } - } - } catch (final DocumentNotFoundException e) { - LOGGER.debug(e.getMessage(), e); - } - return null; - } - - @Override - public void destroy() { - this.couchbase.shutdown(); - } - - @Override - public long size() { - return queryForAllServices().rowsAsObject().size(); - } - - private QueryResult queryForAllServices() { - val query = String.format("REGEX_CONTAINS(%s, \"@class.*:.*RegisteredService\")", couchbase.getBucket()); - val queryResult = couchbase.select(query); - LOGGER.trace("Couchbase query [{}] produced status [{}]", query, queryResult.metaData().status()); - return queryResult; - } -} diff --git a/support/cas-server-support-couchbase-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-couchbase-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 09453a2e1d81..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CouchbaseServiceRegistryConfiguration diff --git a/support/cas-server-support-couchbase-service-registry/src/test/java/org/apereo/cas/services/CouchbaseServiceRegistryTests.java b/support/cas-server-support-couchbase-service-registry/src/test/java/org/apereo/cas/services/CouchbaseServiceRegistryTests.java deleted file mode 100644 index 70d94f58ebc0..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/test/java/org/apereo/cas/services/CouchbaseServiceRegistryTests.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.apereo.cas.services; - -import org.apereo.cas.config.CasCoreNotificationsConfiguration; -import org.apereo.cas.config.CasCoreServicesConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CouchbaseServiceRegistryConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import lombok.SneakyThrows; -import lombok.val; -import org.apache.commons.lang3.RandomUtils; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.parallel.ResourceLock; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.context.event.EventListener; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.TestExecutionListener; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchbaseServiceRegistryTests}. - * - * @author Misagh Moayyed - * @since 4.2.0 - * @deprecated Since 7.0.0 - */ -@SpringBootTest(classes = { - CouchbaseServiceRegistryTests.CouchbaseServiceRegistryTestConfiguration.class, - RefreshAutoConfiguration.class, - CasCoreServicesConfiguration.class, - CasCoreNotificationsConfiguration.class, - CasCoreWebConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - CasCoreUtilConfiguration.class, - CouchbaseServiceRegistryConfiguration.class -}, - properties = { - "cas.service-registry.couchbase.cluster-password=password", - "cas.service-registry.couchbase.cluster-username=admin", - "cas.service-registry.couchbase.bucket=testbucket" - }) -@Tag("Couchbase") -@EnabledIfListeningOnPort(port = 8091) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ResourceLock("Couchbase") -@Getter -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -@TestExecutionListeners({ - DependencyInjectionTestExecutionListener.class, - CouchbaseServiceRegistryTests.DisposingTestExecutionListener.class -}) -@Deprecated(since = "7.0.0") -public class CouchbaseServiceRegistryTests extends AbstractServiceRegistryTests { - - @Autowired - @Qualifier("couchbaseServiceRegistry") - private ServiceRegistry newServiceRegistry; - - @ParameterizedTest - @MethodSource(GET_PARAMETERS) - public void verifySaveWithDefaultId(final Class registeredServiceClass) { - val svc = buildRegisteredServiceInstance(RandomUtils.nextInt(), registeredServiceClass); - svc.setId(RegisteredService.INITIAL_IDENTIFIER_VALUE); - assertEquals(newServiceRegistry.save(svc).getServiceId(), svc.getServiceId(), registeredServiceClass::getName); - } - - public static class DisposingTestExecutionListener implements TestExecutionListener { - @Override - public void afterTestClass(final TestContext testContext) throws Exception { - var registry = testContext.getApplicationContext().getBean("couchbaseServiceRegistry", ServiceRegistry.class); - DisposableBean.class.cast(registry).destroy(); - } - } - - @TestConfiguration(value = "CouchbaseServiceRegistryTestConfiguration", proxyBeanMethods = false) - public static class CouchbaseServiceRegistryTestConfiguration { - - @SneakyThrows - @EventListener - public void handleCouchbaseSaveEvent(final CouchbaseRegisteredServiceSavedEvent event) { - Thread.sleep(100); - } - - @SneakyThrows - @EventListener - public void handleCouchbaseDeleteEvent(final CouchbaseRegisteredServiceDeletedEvent event) { - Thread.sleep(100); - } - } -} diff --git a/support/cas-server-support-couchbase-service-registry/src/test/resources/log4j2-test.xml b/support/cas-server-support-couchbase-service-registry/src/test/resources/log4j2-test.xml deleted file mode 100644 index 0b96c76a64f8..000000000000 --- a/support/cas-server-support-couchbase-service-registry/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-couchbase-service-registry/src/test/resources/services/.donotdelete b/support/cas-server-support-couchbase-service-registry/src/test/resources/services/.donotdelete deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/support/cas-server-support-couchdb-authentication/build.gradle b/support/cas-server-support-couchdb-authentication/build.gradle deleted file mode 100644 index 35ef040a9f5b..000000000000 --- a/support/cas-server-support-couchdb-authentication/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -description = "Apereo CAS CouchDb Authentication Support" -ext { - publishMetadata = true - projectMetadata = [ - category: "Authentication", - title: "Apache CouchDb Authentication" - ] -} -dependencies { - implementation project(":support:cas-server-support-pac4j-core") - implementation project(":support:cas-server-support-couchdb-core") - implementation project(":core:cas-server-core-authentication-api") - implementation project(":support:cas-server-support-pac4j-authentication") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-configuration-api") - - implementation libraries.nimbus - implementation libraries.pac4jcore - implementation libraries.ektorp - implementation libraries.pac4jcouchdb - - testImplementation project(":support:cas-server-support-person-directory") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-notifications") - testImplementation project(":core:cas-server-core-configuration") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core") - - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - -} diff --git a/support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/authentication/CouchDbAuthenticationHandler.java b/support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/authentication/CouchDbAuthenticationHandler.java deleted file mode 100644 index bfce62cc3227..000000000000 --- a/support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/authentication/CouchDbAuthenticationHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apereo.cas.authentication; - -import org.apereo.cas.authentication.principal.PrincipalFactory; -import org.apereo.cas.integration.pac4j.authentication.handler.support.UsernamePasswordWrapperAuthenticationHandler; -import org.apereo.cas.services.ServicesManager; - -import org.pac4j.jee.context.session.JEESessionStore; - -/** - * This is {@link CouchDbAuthenticationHandler}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Deprecated(since = "7.0.0") -public class CouchDbAuthenticationHandler extends UsernamePasswordWrapperAuthenticationHandler { - public CouchDbAuthenticationHandler(final String name, final ServicesManager servicesManager, - final PrincipalFactory principalFactory, final int order) { - super(name, servicesManager, principalFactory, order, JEESessionStore.INSTANCE); - } -} diff --git a/support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/config/CouchDbAuthenticationConfiguration.java b/support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/config/CouchDbAuthenticationConfiguration.java deleted file mode 100644 index 883459937889..000000000000 --- a/support/cas-server-support-couchdb-authentication/src/main/java/org/apereo/cas/config/CouchDbAuthenticationConfiguration.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer; -import org.apereo.cas.authentication.AuthenticationHandler; -import org.apereo.cas.authentication.CouchDbAuthenticationHandler; -import org.apereo.cas.authentication.principal.PrincipalFactory; -import org.apereo.cas.authentication.principal.PrincipalFactoryUtils; -import org.apereo.cas.authentication.principal.PrincipalNameTransformerUtils; -import org.apereo.cas.authentication.principal.PrincipalResolver; -import org.apereo.cas.authentication.support.password.PasswordEncoderUtils; -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultProfileCouchDbRepository; -import org.apereo.cas.couchdb.core.ProfileCouchDbRepository; -import org.apereo.cas.services.ServicesManager; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.pac4j.core.credentials.password.SpringSecurityPasswordEncoder; -import org.pac4j.couch.profile.service.CouchProfileService; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CouchDbAuthenticationConfiguration}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Authentication, module = "couchdb") -@Slf4j -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchDbAuthenticationConfiguration { - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "authenticationCouchDbFactory") - public CouchDbConnectorFactory authenticationCouchDbFactory(final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getAuthn().getCouchDb(), objectMapperFactory); - } - - @ConditionalOnMissingBean(name = "authenticationCouchDbRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public ProfileCouchDbRepository authenticationCouchDbRepository( - @Qualifier("authenticationCouchDbFactory") - final CouchDbConnectorFactory authenticationCouchDbFactory, final CasConfigurationProperties casProperties) { - return new DefaultProfileCouchDbRepository(authenticationCouchDbFactory.getCouchDbConnector(), - casProperties.getAuthn().getCouchDb().isCreateIfNotExists()); - } - - @ConditionalOnMissingBean(name = "couchDbAuthenticationEventExecutionPlanConfigurer") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuthenticationEventExecutionPlanConfigurer couchDbAuthenticationEventExecutionPlanConfigurer( - @Qualifier("couchDbAuthenticationHandler") - final AuthenticationHandler authenticationHandler, - @Qualifier(PrincipalResolver.BEAN_NAME_PRINCIPAL_RESOLVER) - final PrincipalResolver defaultPrincipalResolver) { - return plan -> plan.registerAuthenticationHandlerWithPrincipalResolver(authenticationHandler, defaultPrincipalResolver); - } - - @ConditionalOnMissingBean(name = "couchDbPrincipalFactory") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public PrincipalFactory couchDbPrincipalFactory() { - return PrincipalFactoryUtils.newPrincipalFactory(); - } - - @ConditionalOnMissingBean(name = "couchDbAuthenticationHandler") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public AuthenticationHandler couchDbAuthenticationHandler( - @Qualifier("couchDbAuthenticatorProfileService") - final CouchProfileService couchProfileService, - @Qualifier("couchDbPrincipalFactory") - final PrincipalFactory principalFactory, final CasConfigurationProperties casProperties, - @Qualifier(ServicesManager.BEAN_NAME) - final ServicesManager servicesManager) { - val couchDb = casProperties.getAuthn().getCouchDb(); - val handler = new CouchDbAuthenticationHandler(couchDb.getName(), servicesManager, principalFactory, couchDb.getOrder()); - handler.setAuthenticator(couchProfileService); - handler.setPrincipalNameTransformer(PrincipalNameTransformerUtils.newPrincipalNameTransformer(couchDb.getPrincipalTransformation())); - return handler; - } - - @ConditionalOnMissingBean(name = "couchDbAuthenticatorProfileService") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CouchProfileService couchDbAuthenticatorProfileService( - @Qualifier("authenticationCouchDbFactory") - final CouchDbConnectorFactory authenticationCouchDbFactory, final CasConfigurationProperties casProperties, final ConfigurableApplicationContext applicationContext) { - val couchDb = casProperties.getAuthn().getCouchDb(); - LOGGER.info("Connected to CouchDb instance @ [{}] using database [{}]", couchDb.getUrl(), couchDb.getDbName()); - val encoder = new SpringSecurityPasswordEncoder(PasswordEncoderUtils.newPasswordEncoder(couchDb.getPasswordEncoder(), applicationContext)); - val auth = new CouchProfileService(authenticationCouchDbFactory.getCouchDbConnector(), couchDb.getAttributes()); - auth.setUsernameAttribute(couchDb.getUsernameAttribute()); - auth.setPasswordAttribute(couchDb.getPasswordAttribute()); - auth.setPasswordEncoder(encoder); - return auth; - } -} diff --git a/support/cas-server-support-couchdb-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-couchdb-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index b41d701edd4f..000000000000 --- a/support/cas-server-support-couchdb-authentication/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CouchDbAuthenticationConfiguration diff --git a/support/cas-server-support-couchdb-authentication/src/test/java/org/apereo/cas/authentication/CouchDbAuthenticationHandlerTests.java b/support/cas-server-support-couchdb-authentication/src/test/java/org/apereo/cas/authentication/CouchDbAuthenticationHandlerTests.java deleted file mode 100644 index 9a56abbc8aae..000000000000 --- a/support/cas-server-support-couchdb-authentication/src/test/java/org/apereo/cas/authentication/CouchDbAuthenticationHandlerTests.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.apereo.cas.authentication; - -import org.apereo.cas.authentication.principal.PrincipalFactory; -import org.apereo.cas.authentication.principal.Service; -import org.apereo.cas.config.CasCoreAuthenticationConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationHandlersConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationMetadataConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationPolicyConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationPrincipalConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationServiceSelectionStrategyConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationSupportConfiguration; -import org.apereo.cas.config.CasCoreConfiguration; -import org.apereo.cas.config.CasCoreHttpConfiguration; -import org.apereo.cas.config.CasCoreNotificationsConfiguration; -import org.apereo.cas.config.CasCoreServicesAuthenticationConfiguration; -import org.apereo.cas.config.CasCoreServicesConfiguration; -import org.apereo.cas.config.CasCoreTicketCatalogConfiguration; -import org.apereo.cas.config.CasCoreTicketIdGeneratorsConfiguration; -import org.apereo.cas.config.CasCoreTicketsConfiguration; -import org.apereo.cas.config.CasCoreTicketsSerializationConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CasPersonDirectoryConfiguration; -import org.apereo.cas.config.CouchDbAuthenticationConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.ProfileCouchDbRepository; -import org.apereo.cas.logout.config.CasCoreLogoutConfiguration; -import org.apereo.cas.util.CollectionUtils; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import lombok.val; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.pac4j.couch.profile.CouchProfile; -import org.pac4j.couch.profile.service.CouchProfileService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * This is {@link CouchDbAuthenticationHandlerTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@SpringBootTest(classes = { - CasCouchDbCoreConfiguration.class, - CouchDbAuthenticationConfiguration.class, - CasCoreAuthenticationConfiguration.class, - CasCoreServicesAuthenticationConfiguration.class, - CasCoreUtilConfiguration.class, - CasCoreAuthenticationPrincipalConfiguration.class, - CasCoreAuthenticationPolicyConfiguration.class, - CasCoreAuthenticationMetadataConfiguration.class, - CasCoreAuthenticationSupportConfiguration.class, - CasCoreAuthenticationHandlersConfiguration.class, - CasCoreAuthenticationServiceSelectionStrategyConfiguration.class, - CasCoreTicketIdGeneratorsConfiguration.class, - CasCoreHttpConfiguration.class, - CasCoreTicketCatalogConfiguration.class, - CasCoreTicketsSerializationConfiguration.class, - CasCoreTicketsConfiguration.class, - CasCoreNotificationsConfiguration.class, - CasCoreServicesConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - CasPersonDirectoryConfiguration.class, - CasCoreWebConfiguration.class, - CasCoreLogoutConfiguration.class, - CasCoreConfiguration.class, - RefreshAutoConfiguration.class -}, - properties = { - "cas.authn.couch-db.db-name=authentication", - "cas.authn.couch-db.attributes=loc,state", - "cas.authn.couch-db.username-attribute=username", - "cas.authn.couch-db.password-attribute=password", - "cas.authn.couch-db.username=cas", - "cas.authn.couch-db.password=password", - "cas.authn.pac4j.core.typed-id-used=false" - }) -@Tag("CouchDb") -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbAuthenticationHandlerTests { - @Autowired - @Qualifier("authenticationCouchDbFactory") - private CouchDbConnectorFactory couchDbFactory; - - @Autowired - @Qualifier("authenticationCouchDbRepository") - private ProfileCouchDbRepository couchDbRepository; - - @Autowired - @Qualifier("couchDbAuthenticationHandler") - private AuthenticationHandler authenticationHandler; - - @Autowired - @Qualifier("couchDbPrincipalFactory") - private PrincipalFactory principalFactory; - - @Autowired - @Qualifier("couchDbAuthenticatorProfileService") - private CouchProfileService profileService; - - @BeforeEach - public void setUp() { - couchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(couchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initialize(); - RequestContextHolder.setRequestAttributes( - new ServletRequestAttributes(new MockHttpServletRequest(), new MockHttpServletResponse())); - val profile = new CouchProfile(); - profile.build("u1", CollectionUtils.wrap("loc", "Chicago", "state", "Illinois", "username", "u1")); - profileService.create(profile, "p1"); - } - - @AfterEach - public void tearDown() { - couchDbFactory.getCouchDbInstance().deleteDatabase(couchDbFactory.getCouchDbConnector().getDatabaseName()); - } - - @Test - public void verifyAuthentication() throws Exception { - val result = this.authenticationHandler.authenticate(CoreAuthenticationTestUtils - .getCredentialsWithDifferentUsernameAndPassword("u1", "p1"), mock(Service.class)); - assertEquals("u1", result.getPrincipal().getId()); - assertEquals("Chicago", result.getPrincipal().getAttributes().get("loc").get(0)); - assertEquals("Illinois", result.getPrincipal().getAttributes().get("state").get(0)); - } -} diff --git a/support/cas-server-support-couchdb-core/build.gradle b/support/cas-server-support-couchdb-core/build.gradle deleted file mode 100644 index 0d381a94b093..000000000000 --- a/support/cas-server-support-couchdb-core/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -description = "Apereo CAS CouchDB Support Core" -dependencies { - api libraries.ektorp - api project(":api:cas-server-core-api-configuration-model") - - implementation project(":core:cas-server-core-util-api") -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/config/CasCouchDbCoreConfiguration.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/config/CasCouchDbCoreConfiguration.java deleted file mode 100644 index 665b0aed0878..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/config/CasCouchDbCoreConfiguration.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.core.CasObjectMapperFactory; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.ektorp.ViewQuery; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CasCouchDbCoreConfiguration}, defines certain beans via configuration - * while delegating some to Spring namespaces inside the context config file. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Core, module = "couchdb") -@AutoConfiguration -public class CasCouchDbCoreConfiguration { - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - @ConditionalOnMissingBean(name = "defaultObjectMapperFactory") - public ObjectMapperFactory defaultObjectMapperFactory(final ConfigurableApplicationContext applicationContext) { - val objectMapperFactory = new CasObjectMapperFactory(applicationContext); - ViewQuery.setDefaultObjectMapperFactory(objectMapperFactory); - return objectMapperFactory; - } -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CasObjectMapperFactory.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CasObjectMapperFactory.java deleted file mode 100644 index c9310ddf1e66..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CasObjectMapperFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.apereo.cas.couchdb.core; - -import org.apereo.cas.util.serialization.JacksonObjectMapperFactory; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import org.ektorp.impl.StdObjectMapperFactory; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * This is {@link CouchDbConnectorFactory}. - * - * @author Timur Duehr - * @since 6.0.0 - */ -@RequiredArgsConstructor -public class CasObjectMapperFactory extends StdObjectMapperFactory { - private final ConfigurableApplicationContext applicationContext; - - @Override - protected void applyDefaultConfiguration(final ObjectMapper om) { - super.applyDefaultConfiguration(om); - JacksonObjectMapperFactory.configure(applicationContext, om); - } -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbConnectorFactory.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbConnectorFactory.java deleted file mode 100644 index 5b7531a5e4d0..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbConnectorFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.apereo.cas.couchdb.core; - -import org.ektorp.CouchDbConnector; -import org.ektorp.CouchDbInstance; -import org.ektorp.impl.ObjectMapperFactory; - -/** - * This is {@link CouchDbConnectorFactory}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@Deprecated(since = "7.0.0") -public interface CouchDbConnectorFactory { - /** - * Gets object mapper factory. - * - * @return the object mapper factory - */ - ObjectMapperFactory getObjectMapperFactory(); - - /** - * Gets couch db connector. - * - * @return the couch db connector - */ - CouchDbConnector getCouchDbConnector(); - - /** - * Create connector couch db. - * - * @return the couch db connector - */ - CouchDbConnector createConnector(); - - /** - * Create couch db instance. - * - * @return the couch db instance - */ - CouchDbInstance createInstance(); - - /** - * Gets couch db instance. - * - * @return the couch db instance - */ - CouchDbInstance getCouchDbInstance(); - -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbProfileDocument.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbProfileDocument.java deleted file mode 100644 index 4cf7cbc3f0f3..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/CouchDbProfileDocument.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.apereo.cas.couchdb.core; - -import org.apereo.cas.authentication.principal.Principal; -import org.apereo.cas.util.CollectionUtils; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.ektorp.support.CouchDbDocument; - -import java.io.Serial; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * This is {@link CouchDbProfileDocument}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -@Deprecated(since = "7.0.0") -public class CouchDbProfileDocument extends CouchDbDocument implements Principal { - - @Serial - private static final long serialVersionUID = -986478230300427397L; - - /** - * Username. - */ - @JsonProperty - private String username; - - /** - * Linkedid used by pac4j. - */ - @JsonProperty - private String linkedid; - - /** - * Map for storing extra properties when AUP support - * uses shared database (e.g., user database). - */ - @JsonAnySetter - private Map> attributes = new LinkedHashMap<>(0); - - @Override - @JsonAnyGetter - public Map> getAttributes() { - return attributes; - } - - /** - * Gets a single attribute. - * @param key the attribute key to fetch - * @return the attribute value - */ - @JsonIgnore - public Object getAttribute(final String key) { - return attributes.get(key); - } - - /** - * Sets a single attribute. - * @param key the attribute key to set - * @param value the value to be set - */ - @JsonIgnore - public void setAttribute(final String key, final Object value) { - attributes.put(key, CollectionUtils.toCollection(value, ArrayList.class)); - } -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultCouchDbConnectorFactory.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultCouchDbConnectorFactory.java deleted file mode 100644 index 2da631db00c2..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultCouchDbConnectorFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.apereo.cas.couchdb.core; - -import org.apereo.cas.configuration.model.support.couchdb.BaseCouchDbProperties; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apache.commons.lang3.StringUtils; -import org.ektorp.CouchDbConnector; -import org.ektorp.CouchDbInstance; -import org.ektorp.http.HttpClient; -import org.ektorp.http.StdHttpClient; -import org.ektorp.impl.ObjectMapperFactory; -import org.ektorp.impl.StdCouchDbConnector; -import org.ektorp.impl.StdCouchDbInstance; - -/** - * This is {@link DefaultCouchDbConnectorFactory}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@Getter -@RequiredArgsConstructor -@Slf4j -@Deprecated(since = "7.0.0") -public class DefaultCouchDbConnectorFactory implements CouchDbConnectorFactory { - - private final BaseCouchDbProperties couchDbProperties; - - private final ObjectMapperFactory objectMapperFactory; - - @Getter(lazy = true) - private final CouchDbConnector couchDbConnector = createConnector(); - - @Getter(lazy = true) - private final CouchDbInstance couchDbInstance = createInstance(); - - @Getter(lazy = true) - private final HttpClient httpClient = createHttpClient(); - - /** - * Create {@link CouchDbConnector} instance. - * - * @return CouchDbConnector instance from db properties. - */ - @Override - public CouchDbConnector createConnector() { - val connector = new StdCouchDbConnector(couchDbProperties.getDbName(), getCouchDbInstance(), objectMapperFactory); - LOGGER.debug("Connector created: [{}]", connector); - return connector; - } - - @Override - public CouchDbInstance createInstance() { - val instance = new StdCouchDbInstance(getHttpClient()); - LOGGER.debug("Instance created: [{}]", instance); - return instance; - } - - /** - * Create {@link HttpClient} instance. - * - * @return HttpClient instance from db properties. - */ - @SneakyThrows - public HttpClient createHttpClient() { - val builder = new StdHttpClient.Builder() - .url(couchDbProperties.getUrl()) - .maxConnections(couchDbProperties.getMaxConnections()) - .maxCacheEntries(couchDbProperties.getMaxCacheEntries()) - .connectionTimeout(couchDbProperties.getConnectionTimeout()) - .socketTimeout(couchDbProperties.getSocketTimeout()) - .enableSSL(couchDbProperties.isEnableSsl()) - .relaxedSSLSettings(couchDbProperties.isRelaxedSslSettings()) - .caching(couchDbProperties.isCaching()) - .maxObjectSizeBytes(couchDbProperties.getMaxObjectSizeBytes()) - .useExpectContinue(couchDbProperties.isUseExpectContinue()) - .cleanupIdleConnections(couchDbProperties.isCleanupIdleConnections()); - - if (StringUtils.isNotBlank(couchDbProperties.getProxyHost())) { - builder.proxy(couchDbProperties.getProxyHost()); - - if (couchDbProperties.getProxyPort() > 0) { - builder.proxyPort(couchDbProperties.getProxyPort()); - LOGGER.info("CouchDb proxy settings enabled [{}]:[{}]", couchDbProperties.getProxyHost(), couchDbProperties.getProxyPort()); - } else { - LOGGER.debug("Proxy port not set for host [{}] clearing proxy host.", couchDbProperties.getProxyHost()); - builder.proxy(null); - } - } - - if (StringUtils.isNotBlank(couchDbProperties.getUsername())) { - builder.username(couchDbProperties.getUsername()); - } - - if (StringUtils.isNotBlank(couchDbProperties.getPassword())) { - builder.password(couchDbProperties.getPassword()); - } - - val client = builder.build(); - LOGGER.debug("Client created: [{}]", client); - return client; - } -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultProfileCouchDbRepository.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultProfileCouchDbRepository.java deleted file mode 100644 index 7cffe37e6e13..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/DefaultProfileCouchDbRepository.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.apereo.cas.couchdb.core; - -import org.ektorp.CouchDbConnector; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.View; - -/** - * This is {@link DefaultProfileCouchDbRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Deprecated(since = "7.0.0") -public class DefaultProfileCouchDbRepository extends CouchDbRepositorySupport - implements ProfileCouchDbRepository { - public DefaultProfileCouchDbRepository(final CouchDbConnector db, final boolean createIfNotExists) { - super(CouchDbProfileDocument.class, db, "pac4j", createIfNotExists); - } - - @Override - @View(name = "by_username", map = "function(doc) { if(doc.username){ emit(doc.username, doc) } }") - public CouchDbProfileDocument findByUsername(final String username) { - return queryView("by_username", username).stream().findFirst().orElse(null); - } - - @Override - @View(name = "by_linkedid", map = "function(doc) { if(doc.linkedid){ emit(doc.linkedid, doc) } }") - public CouchDbProfileDocument findByLinkedId(final String linkedid) { - return queryView("by_linkedid", linkedid).stream().findFirst().orElse(null); - } - - @Override - public void initialize() { - initStandardDesignDocument(); - } -} diff --git a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/ProfileCouchDbRepository.java b/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/ProfileCouchDbRepository.java deleted file mode 100644 index 5c4ca6eb4c5b..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/java/org/apereo/cas/couchdb/core/ProfileCouchDbRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.apereo.cas.couchdb.core; - -import org.ektorp.support.GenericRepository; - -/** - * This is {@link ProfileCouchDbRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Deprecated(since = "7.0.0") -public interface ProfileCouchDbRepository extends GenericRepository { - /** - * Find by username. - * - * @param username the username - * @return the couch db profile document - */ - CouchDbProfileDocument findByUsername(String username); - - /** - * Find by linked id. - * - * @param linkedId the linked id - * @return the couch db profile document - */ - CouchDbProfileDocument findByLinkedId(String linkedId); - - /** - * Initialize. - */ - void initialize(); -} diff --git a/support/cas-server-support-couchdb-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-couchdb-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index d86e256bdcf7..000000000000 --- a/support/cas-server-support-couchdb-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CasCouchDbCoreConfiguration diff --git a/support/cas-server-support-couchdb-core/src/test/resources/log4j2-test.xml b/support/cas-server-support-couchdb-core/src/test/resources/log4j2-test.xml deleted file mode 100644 index 3a3fa4f1f17f..000000000000 --- a/support/cas-server-support-couchdb-core/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/support/cas-server-support-couchdb-service-registry/build.gradle b/support/cas-server-support-couchdb-service-registry/build.gradle deleted file mode 100644 index b7ea16d48a81..000000000000 --- a/support/cas-server-support-couchdb-service-registry/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -description = "Apereo CAS CouchDB Service Registry" - -ext { - maxParallelForksForTests = 1 -} - -dependencies { - api project(":api:cas-server-core-api-services") - - api libraries.ektorp - - implementation project(":core:cas-server-core-services") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-services-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":core:cas-server-core-services-registry") - - implementation project(":support:cas-server-support-couchdb-core") - - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-notifications") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-authentication-mfa") - testImplementation project(":support:cas-server-support-oauth-services") - testImplementation project(":support:cas-server-support-saml-idp-core") - testImplementation project(":support:cas-server-support-oidc-services") - testImplementation project(":support:cas-server-support-ws-idp-api") - - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") -} diff --git a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/config/CouchDbServiceRegistryConfiguration.java b/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/config/CouchDbServiceRegistryConfiguration.java deleted file mode 100644 index 5859d24908f4..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/config/CouchDbServiceRegistryConfiguration.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.configuration.support.RequiresModule; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.couchdb.services.RegisteredServiceCouchDbRepository; -import org.apereo.cas.services.CouchDbServiceRegistry; -import org.apereo.cas.services.ServiceRegistry; -import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer; -import org.apereo.cas.services.ServiceRegistryListener; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ScopedProxyMode; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * This is {@link CouchDbServiceRegistryConfiguration}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@RequiresModule(name = "cas-server-support-couchdb-service-registry") -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.ServiceRegistry, module = "couchdb") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchDbServiceRegistryConfiguration { - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "serviceRegistryCouchDbFactory") - public CouchDbConnectorFactory serviceRegistryCouchDbFactory( - final ConfigurableApplicationContext applicationContext, - final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getServiceRegistry().getCouchDb(), objectMapperFactory); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "serviceRegistryCouchDbRepository") - public RegisteredServiceCouchDbRepository serviceRegistryCouchDbRepository( - final CasConfigurationProperties casProperties, - @Qualifier("serviceRegistryCouchDbFactory") - final CouchDbConnectorFactory couchDbFactory) { - val couchDbProperties = casProperties.getServiceRegistry().getCouchDb(); - val serviceRepository = new RegisteredServiceCouchDbRepository(couchDbFactory.getCouchDbConnector(), - couchDbProperties.isCreateIfNotExists()); - serviceRepository.initStandardDesignDocument(); - return serviceRepository; - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "couchDbServiceRegistry") - public ServiceRegistry couchDbServiceRegistry( - final ConfigurableApplicationContext applicationContext, - final ObjectProvider> serviceRegistryListeners, - @Qualifier("serviceRegistryCouchDbRepository") - final RegisteredServiceCouchDbRepository serviceRegistryCouchDbRepository) { - return new CouchDbServiceRegistry(applicationContext, serviceRegistryCouchDbRepository, - Optional.ofNullable(serviceRegistryListeners.getIfAvailable()).orElseGet(ArrayList::new)); - } - - @Configuration(value = "CouchDbServiceRegistryPlanConfiguration", proxyBeanMethods = false) - @EnableConfigurationProperties(CasConfigurationProperties.class) - public static class CouchDbServiceRegistryPlanConfiguration { - @Bean - @ConditionalOnMissingBean(name = "couchDbServiceRegistryExecutionPlanConfigurer") - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public ServiceRegistryExecutionPlanConfigurer couchDbServiceRegistryExecutionPlanConfigurer( - @Qualifier("couchDbServiceRegistry") - final ServiceRegistry couchDbServiceRegistry) { - return plan -> plan.registerServiceRegistry(couchDbServiceRegistry); - } - } - -} diff --git a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepository.java b/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepository.java deleted file mode 100644 index 422c607d4230..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepository.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apereo.cas.couchdb.services; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.ektorp.CouchDbConnector; -import org.ektorp.DocumentNotFoundException; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.UpdateHandler; -import org.ektorp.support.View; - -/** - * This is {@link RegisteredServiceCouchDbRepository}. Typed interface to CouchDB. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@View(name = "all", map = "function(doc) { if (doc.service) { emit(doc._id, doc) } }") -@Slf4j -@Deprecated(since = "7.0.0") -public class RegisteredServiceCouchDbRepository extends CouchDbRepositorySupport { - public RegisteredServiceCouchDbRepository(final CouchDbConnector db, final boolean createIfNotExists) { - super(RegisteredServiceDocument.class, db, createIfNotExists); - } - - /** - * Implements search by serviceId. - * - * @param serviceId The serviceId of the service to find. - * @return The service found or +null+. - */ - @View(name = "by_serviceId", map = "function(doc) { if (doc.service) { emit(doc.service.serviceId, doc._id) }}") - public RegisteredServiceDocument findByServiceId(final String serviceId) { - return queryView("by_serviceId", serviceId).stream().findFirst().orElse(null); - } - - /** - * Implements search by service name. - * - * @param serviceName The service name of the service to find. - * @return The service found or +null+. - */ - @View(name = "by_serviceName", map = "function(doc) { if (doc.service) { emit(doc.service.name, doc._id) }}") - public RegisteredServiceDocument findByServiceName(final String serviceName) { - return queryView("by_serviceName", serviceName).stream().findFirst().orElse(null); - } - - /** - * Overload wrapper for long type. Get service by ID. - * - * @param id Service ID - * @return service - */ - public RegisteredServiceDocument get(final long id) { - try { - return this.get(String.valueOf(id)); - } catch (final DocumentNotFoundException e) { - LOGGER.debug("Service [{}] not found. [{}]", id, e.getMessage()); - return null; - } - } - - /** - * Size of the service database. - * - * @return The service count in the database. - */ - @View(name = "size", map = "function(doc) { if (doc.service) { emit(doc, doc._id) }}", reduce = "_count") - public int size() { - val r = db.queryView(createQuery("size")); - LOGGER.trace("r.isEmpty [{}]", r.isEmpty()); - LOGGER.trace("r.getRows [{}]", r.getRows()); - if (r.isEmpty()) { - return 0; - } - - return r.getRows().get(0).getValueAsInt(); - } - - /** - * Delete a record without revision checks. - * - * @param record record to be deleted - */ - @UpdateHandler(name = "delete_record", file = "RegisteredServiceDocument_delete.js") - public void deleteRecord(final RegisteredServiceDocument record) { - db.callUpdateHandler(stdDesignDocumentId, "delete_record", record.getId(), null); - } - - /** - * Delete records. - */ - public void deleteRecords() { - getAll().forEach(this::deleteRecord); - } -} diff --git a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceDocument.java b/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceDocument.java deleted file mode 100644 index 8a6702fd3e46..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/couchdb/services/RegisteredServiceDocument.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.apereo.cas.couchdb.services; - -import org.apereo.cas.services.RegisteredService; - -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.ektorp.support.CouchDbDocument; - -import java.io.Serial; - -/** - * This is {@link RegisteredServiceDocument}. Wraps a {@link RegisteredService} for use with CouchDB. - * - * @author Timur Duehr - * @since 5.3.0 - */ -@Getter -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) -@NoArgsConstructor -public class RegisteredServiceDocument extends CouchDbDocument { - @Serial - private static final long serialVersionUID = -6787906520673248670L; - private RegisteredService service; - - public RegisteredServiceDocument(final RegisteredService service) { - this.setId(String.valueOf(service.getId())); - this.service = service; - } -} diff --git a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/services/CouchDbServiceRegistry.java b/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/services/CouchDbServiceRegistry.java deleted file mode 100644 index 2c1668ad8289..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/main/java/org/apereo/cas/services/CouchDbServiceRegistry.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.apereo.cas.services; - -import org.apereo.cas.couchdb.services.RegisteredServiceCouchDbRepository; -import org.apereo.cas.couchdb.services.RegisteredServiceDocument; -import org.apereo.cas.util.RandomUtils; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.springframework.context.ConfigurableApplicationContext; - -import java.util.Collection; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * This is {@link CouchDbServiceRegistry}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchDbServiceRegistry extends AbstractServiceRegistry { - - private final RegisteredServiceCouchDbRepository dbClient; - - public CouchDbServiceRegistry(final ConfigurableApplicationContext applicationContext, - final RegisteredServiceCouchDbRepository dbClient, - final Collection serviceRegistryListeners) { - super(applicationContext, serviceRegistryListeners); - this.dbClient = dbClient; - } - - @Override - public RegisteredService save(final RegisteredService registeredService) { - LOGGER.debug("Saving service [{}]", registeredService.getName()); - if (registeredService.getId() < 0) { - registeredService.setId(RandomUtils.nextLong()); - } - val svc = dbClient.get(registeredService.getId()); - invokeServiceRegistryListenerPreSave(registeredService); - if (svc != null) { - val doc = new RegisteredServiceDocument(registeredService); - doc.setRevision(svc.getRevision()); - dbClient.update(doc); - LOGGER.debug("Service [{}] with id [{}] updated", registeredService.getName(), registeredService.getId()); - } else { - dbClient.add(new RegisteredServiceDocument(registeredService)); - LOGGER.debug("New service [{}] with id [{}] created", registeredService.getName(), registeredService.getId()); - } - return registeredService; - } - - @Override - public boolean delete(final RegisteredService service) { - LOGGER.debug("Deleting service [{}]", service.getName()); - dbClient.deleteRecord(new RegisteredServiceDocument(service)); - LOGGER.debug("Successfully deleted service [{}] with id [{}].", service.getName(), service.getId()); - return true; - } - - @Override - public void deleteAll() { - dbClient.deleteRecords(); - } - - @Override - public Collection load() { - return dbClient.getAll() - .stream() - .map(RegisteredServiceDocument::getService) - .map(this::invokeServiceRegistryListenerPostLoad) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - @Override - public RegisteredService findServiceById(final long id) { - val doc = dbClient.get(id); - if (doc != null) { - return doc.getService(); - } - return null; - } - - @Override - public RegisteredService findServiceByExactServiceId(final String id) { - val doc = dbClient.findByServiceId(id); - if (doc == null) { - return null; - } - return doc.getService(); - } - - @Override - public RegisteredService findServiceByExactServiceName(final String name) { - val doc = dbClient.findByServiceName(name); - if (doc == null) { - return null; - } - return doc.getService(); - } - - @Override - public long size() { - return dbClient.size(); - } -} diff --git a/support/cas-server-support-couchdb-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-couchdb-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 207efe189d40..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CouchDbServiceRegistryConfiguration diff --git a/support/cas-server-support-couchdb-service-registry/src/main/resources/org/apereo/cas/couchdb/services/RegisteredServiceDocument_delete.js b/support/cas-server-support-couchdb-service-registry/src/main/resources/org/apereo/cas/couchdb/services/RegisteredServiceDocument_delete.js deleted file mode 100644 index 0488fb2d3240..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/main/resources/org/apereo/cas/couchdb/services/RegisteredServiceDocument_delete.js +++ /dev/null @@ -1,8 +0,0 @@ -function(doc, req){ - if (!doc){ - return [null, "No record supplied."] - } else { - doc['_deleted'] = true - return [doc, "Record Deleted."] - } -} diff --git a/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/AllTestsSuite.java b/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/AllTestsSuite.java deleted file mode 100644 index be0cc2be5e10..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/AllTestsSuite.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.apereo.cas; - -import org.apereo.cas.couchdb.services.RegisteredServiceCouchDbRepositoryTests; -import org.apereo.cas.services.CouchDbServiceRegistryTests; - -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; - -/** - * This is {@link AllTestsSuite}. - * - * @author Misagh Moayyed - * @since 6.0.0-RC3 - */ -@SelectClasses({ - RegisteredServiceCouchDbRepositoryTests.class, - CouchDbServiceRegistryTests.class -}) -@Suite -public class AllTestsSuite { -} diff --git a/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepositoryTests.java b/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepositoryTests.java deleted file mode 100644 index 39d49b90f14c..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/couchdb/services/RegisteredServiceCouchDbRepositoryTests.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.apereo.cas.couchdb.services; - -import org.apereo.cas.config.CasCoreNotificationsConfiguration; -import org.apereo.cas.config.CasCoreServicesConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CouchDbServiceRegistryConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link RegisteredServiceCouchDbRepositoryTests}. - * - * @author Misagh Moayyed - * @since 6.3.0 - * @deprecated Since 7 - */ -@SpringBootTest(classes = { - RefreshAutoConfiguration.class, - CasCoreUtilConfiguration.class, - CasCoreWebConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - CasCouchDbCoreConfiguration.class, - CasCoreNotificationsConfiguration.class, - CasCoreServicesConfiguration.class, - CouchDbServiceRegistryConfiguration.class -}, - properties = { - "cas.service-registry.couch-db.username=cas", - "cas.service-registry.couch-db.caching=false", - "cas.service-registry.couch-db.password=password" - }) -@Tag("CouchDb") -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class RegisteredServiceCouchDbRepositoryTests { - @Autowired - @Qualifier("serviceRegistryCouchDbRepository") - private RegisteredServiceCouchDbRepository serviceRegistryCouchDbRepository; - - @Test - public void verifyOperation() { - assertNull(serviceRegistryCouchDbRepository.findByServiceName("unknown-service")); - assertNull(serviceRegistryCouchDbRepository.get(554433)); - } - -} diff --git a/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/services/CouchDbServiceRegistryTests.java b/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/services/CouchDbServiceRegistryTests.java deleted file mode 100644 index 51f1a33a17d2..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/test/java/org/apereo/cas/services/CouchDbServiceRegistryTests.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.apereo.cas.services; - -import org.apereo.cas.config.CasCoreNotificationsConfiguration; -import org.apereo.cas.config.CasCoreServicesConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CouchDbServiceRegistryConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * This is {@link CouchDbServiceRegistryTests}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@SpringBootTest(classes = { - RefreshAutoConfiguration.class, - CasCoreUtilConfiguration.class, - CasCouchDbCoreConfiguration.class, - CasCoreNotificationsConfiguration.class, - CasCoreServicesConfiguration.class, - CasCoreWebConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - CouchDbServiceRegistryConfiguration.class -}, - properties = { - "cas.service-registry.couch-db.username=cas", - "cas.service-registry.couch-db.caching=false", - "cas.service-registry.couch-db.password=password" - }) -@Tag("CouchDb") -@EnabledIfListeningOnPort(port = 5984) -@Getter -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -@Deprecated(since = "7.0.0") -public class CouchDbServiceRegistryTests extends AbstractServiceRegistryTests { - - @Autowired - @Qualifier("couchDbServiceRegistry") - private ServiceRegistry newServiceRegistry; - - @Test - public void verifyOperation() { - assertNull(newServiceRegistry.findServiceByExactServiceName("unknown-service")); - assertNull(newServiceRegistry.findServiceByExactServiceId("unknown-service")); - assertNull(newServiceRegistry.findServiceById(554433)); - } - -} diff --git a/support/cas-server-support-couchdb-service-registry/src/test/resources/log4j2-test.xml b/support/cas-server-support-couchdb-service-registry/src/test/resources/log4j2-test.xml deleted file mode 100644 index ad0b8b6d367d..000000000000 --- a/support/cas-server-support-couchdb-service-registry/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-couchdb-ticket-registry/build.gradle b/support/cas-server-support-couchdb-ticket-registry/build.gradle deleted file mode 100644 index b129ffd5dde9..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -description = "Apereo CAS CouchDB Ticket Registry" -ext { - publishMetadata = true - projectMetadata = [ - category: "Ticket Registries", - title: "Apache CouchDb Ticket Registry" - ] -} -dependencies { - api libraries.ektorp - - implementation project(":core:cas-server-core-tickets-api") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":support:cas-server-support-couchdb-core") - - testImplementation project(":support:cas-server-support-person-directory") - - testImplementation project(":core:cas-server-core") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-cookie") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-configuration") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-logout-api") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core-services-authentication") - testImplementation project(":core:cas-server-core-authentication-api") - testImplementation project(":core:cas-server-core-authentication-attributes") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-web-api") - testImplementation project(":core:cas-server-core-notifications") - - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-services", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-tickets", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") -} diff --git a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/config/CouchDbTicketRegistryConfiguration.java b/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/config/CouchDbTicketRegistryConfiguration.java deleted file mode 100644 index d726de4776fd..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/config/CouchDbTicketRegistryConfiguration.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.couchdb.tickets.TicketRepository; -import org.apereo.cas.ticket.TicketCatalog; -import org.apereo.cas.ticket.registry.CouchDbTicketRegistry; -import org.apereo.cas.ticket.registry.NoOpTicketRegistryCleaner; -import org.apereo.cas.ticket.registry.TicketRegistry; -import org.apereo.cas.ticket.registry.TicketRegistryCleaner; -import org.apereo.cas.ticket.serialization.TicketSerializationManager; -import org.apereo.cas.util.CoreTicketUtils; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CouchDbTicketRegistryConfiguration}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.TicketRegistry, module = "couchdb") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchDbTicketRegistryConfiguration { - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - @ConditionalOnMissingBean(name = "ticketRegistryCouchDbFactory") - public CouchDbConnectorFactory ticketRegistryCouchDbFactory(final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getTicket().getRegistry().getCouchDb(), objectMapperFactory); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "ticketRegistryCouchDbRepository") - public TicketRepository ticketRegistryCouchDbRepository(final CasConfigurationProperties casProperties, - @Qualifier("ticketRegistryCouchDbFactory") - final CouchDbConnectorFactory ticketRegistryCouchDbFactory) { - val couchDbProperties = casProperties.getTicket().getRegistry().getCouchDb(); - val ticketRepository = new TicketRepository(ticketRegistryCouchDbFactory.getCouchDbConnector(), couchDbProperties.isCreateIfNotExists()); - ticketRepository.initStandardDesignDocument(); - return ticketRepository; - } - - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @Bean - @ConditionalOnMissingBean(name = "couchDbTicketRegistry") - public TicketRegistry ticketRegistry(final CasConfigurationProperties casProperties, - @Qualifier(TicketCatalog.BEAN_NAME) - final TicketCatalog ticketCatalog, - @Qualifier(TicketSerializationManager.BEAN_NAME) - final TicketSerializationManager ticketSerializationManager, - @Qualifier("ticketRegistryCouchDbRepository") - final TicketRepository ticketRegistryCouchDbRepository) { - val couchDb = casProperties.getTicket().getRegistry().getCouchDb(); - val cipherExecutor = CoreTicketUtils.newTicketRegistryCipherExecutor(couchDb.getCrypto(), "couch-db"); - return new CouchDbTicketRegistry(cipherExecutor, ticketSerializationManager, ticketCatalog, ticketRegistryCouchDbRepository, couchDb.getRetries()); - } - - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - @ConditionalOnMissingBean(name = "couchDbTicketRegistryCleaner") - @Lazy(false) - public TicketRegistryCleaner ticketRegistryCleaner() { - return NoOpTicketRegistryCleaner.getInstance(); - } -} diff --git a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketDocument.java b/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketDocument.java deleted file mode 100644 index 8a354221b196..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketDocument.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.apereo.cas.couchdb.tickets; - -import org.apereo.cas.ticket.Ticket; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.ektorp.support.CouchDbDocument; - -import java.io.Serial; - -/** - * This is {@link TicketDocument}. Wraps a {@link Ticket} for use with CouchDB. - * - * @author Timur Duehr - * @since 5.3.0 - */ -@Getter -@Setter -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) -@NoArgsConstructor -public class TicketDocument extends CouchDbDocument { - @Serial - private static final long serialVersionUID = -5460618381339711000L; - - private Ticket ticket; - - @JsonCreator - public TicketDocument(@JsonProperty("ticket") final Ticket ticket) { - this.setId(ticket.getId()); - this.ticket = ticket; - } -} diff --git a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketRepository.java b/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketRepository.java deleted file mode 100644 index 40d091f6eff8..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/couchdb/tickets/TicketRepository.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.apereo.cas.couchdb.tickets; - -import org.ektorp.BulkDeleteDocument; -import org.ektorp.CouchDbConnector; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.View; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * This is {@link TicketDocument}. Typed interface to CouchDB. - * - * @author Timur Duehr - * @since 5.3.0 - */ -@View(name = "all", map = "function(doc) { emit(null, doc._id) }") -public class TicketRepository extends CouchDbRepositorySupport { - public TicketRepository(final CouchDbConnector db) { - this(db, true); - } - - public TicketRepository(final CouchDbConnector db, final boolean createIfNotExists) { - super(TicketDocument.class, db, createIfNotExists); - } - - /** - * Delete tickets. - * - * @param ticketDocuments tickets to be deleted. - * @return number of tickets deleted - */ - public long delete(final List ticketDocuments) { - return db.executeBulk(ticketDocuments.stream() - .map(BulkDeleteDocument::of) - .collect(Collectors.toList())) - .size(); - } - - /** - * Gets current document revision. - * - * @param id Document id to get revision. - * @return current document revision. - */ - public String getCurrentRevision(final String id) { - return db.getCurrentRevision(id); - } -} diff --git a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistry.java b/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistry.java deleted file mode 100644 index ca5d62d40ee7..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistry.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.apereo.cas.ticket.registry; - -import org.apereo.cas.couchdb.tickets.TicketDocument; -import org.apereo.cas.couchdb.tickets.TicketRepository; -import org.apereo.cas.ticket.Ticket; -import org.apereo.cas.ticket.TicketCatalog; -import org.apereo.cas.ticket.serialization.TicketSerializationManager; -import org.apereo.cas.util.crypto.CipherExecutor; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apache.commons.lang3.StringUtils; -import org.ektorp.DbAccessException; -import org.ektorp.DocumentNotFoundException; -import org.ektorp.UpdateConflictException; - -import java.util.Collection; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * This is {@link CouchDbTicketRegistry }. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchDbTicketRegistry extends AbstractTicketRegistry { - - private final TicketRepository couchDb; - - private final int conflictRetries; - - public CouchDbTicketRegistry(final CipherExecutor cipherExecutor, final TicketSerializationManager ticketSerializationManager, - final TicketCatalog ticketCatalog, final TicketRepository couchDb, final int conflictRetries) { - super(cipherExecutor, ticketSerializationManager, ticketCatalog); - this.couchDb = couchDb; - this.conflictRetries = conflictRetries; - } - - @Override - public long deleteSingleTicket(final String ticketIdToDelete) { - val ticketId = digest(ticketIdToDelete); - LOGGER.debug("Deleting ticket [{}]", ticketIdToDelete); - var exception = (DbAccessException) null; - var success = false; - val ticketDocument = new TicketDocument(); - ticketDocument.setRevision(couchDb.getCurrentRevision(ticketId)); - ticketDocument.setId(ticketId); - for (var retries = 0; retries < conflictRetries && exception == null && !success; retries++) { - try { - couchDb.remove(ticketDocument); - success = true; - } catch (final UpdateConflictException e) { - ticketDocument.setRevision(couchDb.getCurrentRevision(ticketId)); - if (retries + 1 == conflictRetries) { - exception = e; - } - } catch (final DocumentNotFoundException e) { - exception = e; - } - } - - if (exception != null) { - LOGGER.warn("Could not delete [{}] [{}]", ticketId, exception.getMessage()); - } else if (success) { - LOGGER.trace("Successfully deleted ticket [{}].", ticketId); - } else { - LOGGER.warn("Could not delete [{}] - failed.", ticketId); - } - - return success ? 1 : 0; - } - - @Override - public void addTicketInternal(final Ticket ticketToAdd) throws Exception { - val encodedTicket = encodeTicket(ticketToAdd); - LOGGER.trace("Adding ticket [{}]", encodedTicket.getId()); - couchDb.add(new TicketDocument(encodedTicket)); - } - - @Override - public Ticket getTicket(final String ticketId, final Predicate predicate) { - LOGGER.trace("Locating ticket id [{}]", ticketId); - val encTicketId = digest(ticketId); - if (StringUtils.isBlank(encTicketId)) { - LOGGER.trace("Ticket id [{}] could not be found", encTicketId); - return null; - } - - try { - val document = this.couchDb.get(encTicketId); - val t = document.getTicket(); - LOGGER.trace("Got ticket [{}] from the registry.", t); - - val decoded = decodeTicket(t); - if (predicate.test(decoded)) { - return decoded; - } - return null; - } catch (final DocumentNotFoundException ignored) { - LOGGER.trace("Ticket [{}] not found in the registry.", encTicketId); - } - return null; - } - - @Override - public long deleteAll() { - return couchDb.delete(couchDb.getAll()); - } - - @Override - public Collection getTickets() { - return decodeTickets(couchDb.getAll().stream().map(TicketDocument::getTicket).collect(Collectors.toList())); - } - - @Override - public Ticket updateTicket(final Ticket ticket) throws Exception { - val encodedTicket = encodeTicket(ticket); - LOGGER.trace("Updating [{}]", encodedTicket.getId()); - var success = false; - val doc = new TicketDocument(encodedTicket); - doc.setRevision(couchDb.getCurrentRevision(encodedTicket.getId())); - for (var retries = 0; retries < conflictRetries; retries++) { - try { - couchDb.update(doc); - success = true; - } catch (final DbAccessException e) { - doc.setRevision(couchDb.getCurrentRevision(encodedTicket.getId())); - LOGGER.warn("Could not update [{}] [{}]", encodedTicket.getId(), e.getMessage()); - } - if (success) { - LOGGER.trace("Successfully updated ticket [{}].", encodedTicket.getId()); - return ticket; - } - } - return null; - } -} diff --git a/support/cas-server-support-couchdb-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-couchdb-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 3bc5fd3416a5..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CouchDbTicketRegistryConfiguration diff --git a/support/cas-server-support-couchdb-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistryTests.java b/support/cas-server-support-couchdb-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistryTests.java deleted file mode 100644 index 4ba88986f16e..000000000000 --- a/support/cas-server-support-couchdb-ticket-registry/src/test/java/org/apereo/cas/ticket/registry/CouchDbTicketRegistryTests.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.apereo.cas.ticket.registry; - -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CouchDbTicketRegistryConfiguration; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.tickets.TicketRepository; -import org.apereo.cas.mock.MockTicketGrantingTicket; -import org.apereo.cas.util.crypto.CipherExecutor; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.val; -import org.ektorp.DbAccessException; -import org.ektorp.DocumentNotFoundException; -import org.ektorp.UpdateConflictException; -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.TestPropertySource; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * This is {@link CouchDbTicketRegistryTests}. - * - * @author Timur Duehr - * @since 5.3.0 - * @deprecated Since 7 - */ -@Import({ - CasCouchDbCoreConfiguration.class, - CouchDbTicketRegistryConfiguration.class -}) -@TestPropertySource( - properties = { - "cas.ticket.registry.couch-db.username=cas", - "cas.ticket.registry.couch-db.caching=false", - "cas.ticket.registry.couch-db.password=password" - }) -@Tag("CouchDb") -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbTicketRegistryTests extends BaseTicketRegistryTests { - - @Autowired - @Qualifier("ticketRegistryCouchDbRepository") - private TicketRepository ticketRepository; - - @Autowired - @Qualifier(TicketRegistry.BEAN_NAME) - private TicketRegistry ticketRegistry; - - @Autowired - @Qualifier("ticketRegistryCouchDbFactory") - private CouchDbConnectorFactory couchDbFactory; - - @Override - public TicketRegistry getNewTicketRegistry() { - couchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(couchDbFactory.getCouchDbConnector().getDatabaseName()); - ticketRepository.initStandardDesignDocument(); - return ticketRegistry; - } - - @RepeatedTest(1) - public void verifyFails() throws Exception { - val couchDb = mock(TicketRepository.class); - doThrow(new DbAccessException()).when(couchDb).update(any()); - val registry = new CouchDbTicketRegistry(CipherExecutor.noOp(), ticketSerializationManager, ticketCatalog, couchDb, 1); - assertNull(registry.updateTicket(new MockTicketGrantingTicket("casuser"))); - - doThrow(new UpdateConflictException()).when(couchDb).remove(any()); - assertEquals(0, registry.deleteTicket(new MockTicketGrantingTicket("casuser"))); - - doThrow(new DocumentNotFoundException("path")).when(couchDb).remove(any()); - assertEquals(0, registry.deleteTicket(new MockTicketGrantingTicket("casuser"))); - } - - @Override - protected boolean isIterableRegistry() { - return false; - } -} diff --git a/support/cas-server-support-events-couchdb/build.gradle b/support/cas-server-support-events-couchdb/build.gradle deleted file mode 100644 index 063a4a3eb60a..000000000000 --- a/support/cas-server-support-events-couchdb/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -description = "Apereo CAS Events Consumer CouchDb" -ext { - publishMetadata = true - projectMetadata = [ - category: "Events", - title: "Authentication Events via Apache CouchDb" - ] -} -dependencies { - implementation project(":core:cas-server-core-events") - implementation project(":core:cas-server-core-events-api") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-configuration-api") - implementation project(":support:cas-server-support-couchdb-core") - - implementation libraries.ektorp - - testImplementation project(path: ":core:cas-server-core-authentication", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-tickets", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-events", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-configuration") - testImplementation project(":core:cas-server-core-services") -} diff --git a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/config/CouchDbEventsConfiguration.java b/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/config/CouchDbEventsConfiguration.java deleted file mode 100644 index 9513900e0506..000000000000 --- a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/config/CouchDbEventsConfiguration.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.couchdb.events.EventCouchDbRepository; -import org.apereo.cas.support.events.CasEventRepository; -import org.apereo.cas.support.events.CasEventRepositoryFilter; -import org.apereo.cas.support.events.CouchDbCasEventRepository; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * This is {@link CouchDbEventsConfiguration}, defines certain beans via configuration - * while delegating some to Spring namespaces inside the context config file. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@EnableConfigurationProperties(CasConfigurationProperties.class) -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Events, module = "couchdb") -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class CouchDbEventsConfiguration { - - @ConditionalOnMissingBean(name = "couchDbEventRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public EventCouchDbRepository couchDbEventRepository( - @Qualifier("eventCouchDbFactory") - final CouchDbConnectorFactory eventCouchDbFactory, final CasConfigurationProperties casProperties) { - val repository = new EventCouchDbRepository(eventCouchDbFactory.getCouchDbConnector(), - casProperties.getEvents().getCouchDb().isCreateIfNotExists(), - eventCouchDbFactory.getObjectMapperFactory()); - repository.initStandardDesignDocument(); - return repository; - } - - @ConditionalOnMissingBean(name = "eventCouchDbFactory") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CouchDbConnectorFactory eventCouchDbFactory(final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getEvents().getCouchDb(), objectMapperFactory); - } - - @ConditionalOnMissingBean(name = "couchDbCasEventRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CasEventRepository casEventRepository( - @Qualifier("couchDbEventRepository") - final EventCouchDbRepository eventCouchDbRepository, - @Qualifier("couchDbEventRepositoryFilter") - final CasEventRepositoryFilter couchDbEventRepositoryFilter, - final CasConfigurationProperties casProperties) { - return new CouchDbCasEventRepository(couchDbEventRepositoryFilter, - eventCouchDbRepository, casProperties.getEvents().getCouchDb().isAsynchronous()); - } - - @ConditionalOnMissingBean(name = "couchDbEventRepositoryFilter") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CasEventRepositoryFilter couchDbEventRepositoryFilter() { - return CasEventRepositoryFilter.noOp(); - } -} diff --git a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/CouchDbCasEvent.java b/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/CouchDbCasEvent.java deleted file mode 100644 index 8ab10a67ccc8..000000000000 --- a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/CouchDbCasEvent.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.apereo.cas.couchdb.events; - -import org.apereo.cas.support.events.dao.CasEvent; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.Accessors; - -import java.io.Serial; -import java.util.Map; - -/** - * This is {@link CouchDbCasEvent}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@ToString -@Getter -@Setter -@AllArgsConstructor -@Accessors(chain = true) -@Deprecated(since = "7.0.0") -public class CouchDbCasEvent extends CasEvent { - - @Serial - private static final long serialVersionUID = 7707486620134127284L; - - /** - * CouchDb id. - */ - @JsonProperty("_id") - private String cid; - - /** - * CouchDb revision. - */ - @JsonProperty("_rev") - private String rev; - - @JsonCreator - public CouchDbCasEvent(@JsonProperty("_id") final String cid, - @JsonProperty("_rev") final String rev, - @JsonProperty("id") final long id, - @JsonProperty("type") final @NonNull String type, - @JsonProperty("principalId") final @NonNull String principalId, - @JsonProperty("creationTime") final @NonNull String creationTime, - @JsonProperty("properties") final Map properties - ) { - super(id, type, principalId, creationTime, properties); - this.cid = cid; - this.rev = rev; - } - - /** - * Copy constructor. - * @param event Event to copy from. - */ - public CouchDbCasEvent(final CasEvent event) { - super(event.getId(), event.getType(), event.getPrincipalId(), event.getCreationTime(), event.getProperties()); - } -} diff --git a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/EventCouchDbRepository.java b/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/EventCouchDbRepository.java deleted file mode 100644 index db22e014adec..000000000000 --- a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/couchdb/events/EventCouchDbRepository.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.apereo.cas.couchdb.events; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.val; -import org.ektorp.ComplexKey; -import org.ektorp.CouchDbConnector; -import org.ektorp.impl.ObjectMapperFactory; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.GenerateView; -import org.ektorp.support.View; -import org.jooq.lambda.Unchecked; - -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * This is {@link EventCouchDbRepository}. Typed interface to CouchDB. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@View(name = "all", map = "function(doc) { emit(doc._id, doc) }") -@Deprecated(since = "7.0.0") -public class EventCouchDbRepository extends CouchDbRepositorySupport { - private final ObjectMapper objectMapper; - - public EventCouchDbRepository(final CouchDbConnector db, - final boolean createIfNotExists, - final ObjectMapperFactory objectMapperFactory) { - super(CouchDbCasEvent.class, db, createIfNotExists); - this.objectMapper = objectMapperFactory.createObjectMapper(db); - } - - /** - * Find by event type. - * - * @param type event type - * @return events of requested type - */ - @GenerateView - public Stream findByType(final String type) { - val query = createQuery("by_type").includeDocs(true).key(type); - return StreamSupport.stream(db.queryForStreamingView(query).spliterator(), false) - .map(Unchecked.function(row -> objectMapper.readValue(row.getDoc(), CouchDbCasEvent.class))); - } - - /** - * Fund by type since a given date. - * - * @param type type to search for - * @param dt time to search since - * @return events of the given type since the given time - */ - public Stream findByTypeSince(final String type, final ZonedDateTime dt) { - val now = ZonedDateTime.now(ZoneOffset.UTC); - return findByType(type) - .filter(event -> { - val eventDate = ZonedDateTime.parse(event.getCreationTime()); - return eventDate.isEqual(dt) || (eventDate.isAfter(dt) && eventDate.isBefore(now)); - }); - } - - /** - * Find by type and principal id. - * - * @param type event type - * @param principalId principal to search for - * @return events of requested type and principal - */ - @View(name = "by_type_for_principal_id", map = "function(doc) { emit([doc.type, doc.principalId], doc) }") - public Stream findByTypeForPrincipalId(final String type, final String principalId) { - val query = createQuery("by_type_for_principal_id").includeDocs(true).key(ComplexKey.of(type, principalId)); - return StreamSupport.stream(db.queryForStreamingView(query).spliterator(), false) - .map(Unchecked.function(row -> objectMapper.readValue(row.getDoc(), CouchDbCasEvent.class))); - - } - - /** - * Find by type and principal id. - * - * @param type event type - * @param principalId principal to search for - * @param dt time to search after - * @return events of requested type and principal since given time - */ - public Stream findByTypeForPrincipalSince(final String type, - final String principalId, - final ZonedDateTime dt) { - val now = ZonedDateTime.now(ZoneOffset.UTC); - return findByTypeForPrincipalId(type, principalId) - .filter(event -> { - val eventDate = ZonedDateTime.parse(event.getCreationTime()); - return eventDate.isEqual(dt) || (eventDate.isAfter(dt) && eventDate.isBefore(now)); - }); - } - - /** - * Find by principal. - * - * @param principalId principal to search for - * @return events for the given principal - */ - @GenerateView - public Stream findByPrincipalId(final String principalId) { - val query = createQuery("by_principalId").includeDocs(true).key(principalId); - return StreamSupport.stream(db.queryForStreamingView(query).spliterator(), false) - .map(Unchecked.function(row -> objectMapper.readValue(row.getDoc(), CouchDbCasEvent.class))); - } - - /** - * Find by principal. - * - * @param principalId principal to search for - * @param creationTime time to search after - * @return events for the given principal after the given time - */ - public Stream findByPrincipalSince(final String principalId, - final ZonedDateTime creationTime) { - val now = ZonedDateTime.now(ZoneOffset.UTC); - return findByPrincipalId(principalId) - .filter(event -> { - val eventDate = ZonedDateTime.parse(event.getCreationTime()); - return eventDate.isEqual(creationTime) - || (eventDate.isAfter(creationTime) && eventDate.isBefore(now)); - }); - } -} diff --git a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/support/events/CouchDbCasEventRepository.java b/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/support/events/CouchDbCasEventRepository.java deleted file mode 100644 index 06cefc4cbbd4..000000000000 --- a/support/cas-server-support-events-couchdb/src/main/java/org/apereo/cas/support/events/CouchDbCasEventRepository.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.apereo.cas.support.events; - -import org.apereo.cas.couchdb.events.CouchDbCasEvent; -import org.apereo.cas.couchdb.events.EventCouchDbRepository; -import org.apereo.cas.support.events.dao.AbstractCasEventRepository; -import org.apereo.cas.support.events.dao.CasEvent; - -import lombok.val; -import org.springframework.beans.factory.DisposableBean; - -import java.time.ZonedDateTime; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Stream; - -/** - * This is {@link CouchDbCasEventRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Deprecated(since = "7.0.0") -public class CouchDbCasEventRepository extends AbstractCasEventRepository implements DisposableBean { - - private final EventCouchDbRepository couchDb; - - private final boolean asynchronous; - - private final ExecutorService executorService = Executors.newSingleThreadExecutor( - r -> new Thread(r, "CouchDbCasEventRepositoryThread")); - - public CouchDbCasEventRepository(final CasEventRepositoryFilter eventRepositoryFilter, - final EventCouchDbRepository couchDb, final boolean asynchronous) { - super(eventRepositoryFilter); - this.couchDb = couchDb; - this.asynchronous = asynchronous; - } - - private static Stream castEvents(final Stream events) { - return events; - } - - @Override - public void removeAll() { - couchDb.getAll().forEach(couchDb::remove); - } - - @Override - public Stream load() { - return couchDb.getAll().stream(); - } - - @Override - public Stream getEventsOfTypeForPrincipal(final String type, final String principal) { - return castEvents(couchDb.findByTypeForPrincipalId(type, principal)); - } - - @Override - public Stream getEventsOfTypeForPrincipal(final String type, final String principal, - final ZonedDateTime dateTime) { - return castEvents(couchDb.findByTypeForPrincipalSince(type, principal, dateTime)); - } - - @Override - public Stream getEventsOfType(final String type) { - return castEvents(couchDb.findByType(type)); - } - - @Override - public Stream getEventsOfType(final String type, final ZonedDateTime dateTime) { - return castEvents(couchDb.findByTypeSince(type, dateTime)); - } - - @Override - public Stream getEventsForPrincipal(final String id) { - return castEvents(couchDb.findByPrincipalId(id)); - } - - @Override - public Stream getEventsForPrincipal(final String id, final ZonedDateTime dateTime) { - return castEvents(couchDb.findByPrincipalSince(id, dateTime)); - } - - @Override - public CasEvent saveInternal(final CasEvent event) { - val cdbEvent = new CouchDbCasEvent(event); - if (asynchronous) { - this.executorService.execute(() -> couchDb.add(cdbEvent)); - } else { - couchDb.add(cdbEvent); - } - return cdbEvent; - } - - @Override - public void destroy() { - this.executorService.shutdown(); - } -} diff --git a/support/cas-server-support-events-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-events-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 50ebdc850fd8..000000000000 --- a/support/cas-server-support-events-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.CouchDbEventsConfiguration diff --git a/support/cas-server-support-events-couchdb/src/test/java/org/apereo/cas/support/events/couchdb/CouchDbCasEventRepositoryTests.java b/support/cas-server-support-events-couchdb/src/test/java/org/apereo/cas/support/events/couchdb/CouchDbCasEventRepositoryTests.java deleted file mode 100644 index 607b4f29ea56..000000000000 --- a/support/cas-server-support-events-couchdb/src/test/java/org/apereo/cas/support/events/couchdb/CouchDbCasEventRepositoryTests.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.apereo.cas.support.events.couchdb; - -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CouchDbEventsConfiguration; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.events.EventCouchDbRepository; -import org.apereo.cas.support.events.AbstractCasEventRepositoryTests; -import org.apereo.cas.support.events.CasEventRepository; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; - -/** - * This is {@link CouchDbCasEventRepositoryTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Tag("CouchDb") -@SpringBootTest(classes = { - CasCouchDbCoreConfiguration.class, - CouchDbEventsConfiguration.class, - RefreshAutoConfiguration.class - }, - properties = { - "cas.events.couch-db.asynchronous=false", - "cas.events.couch-db.username=cas", - "cas.events.couch-db.password=password" - }) -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbCasEventRepositoryTests extends AbstractCasEventRepositoryTests { - @Autowired - @Qualifier("couchDbEventRepository") - private EventCouchDbRepository couchDbRepository; - - @Autowired - @Qualifier(CasEventRepository.BEAN_NAME) - private CasEventRepository eventRepository; - - @Autowired - @Qualifier("eventCouchDbFactory") - private CouchDbConnectorFactory couchDbFactory; - - @BeforeEach - public void setUp() { - couchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(couchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initStandardDesignDocument(); - } - - @AfterEach - public void tearDown() { - couchDbFactory.getCouchDbInstance().deleteDatabase(couchDbFactory.getCouchDbConnector().getDatabaseName()); - } -} diff --git a/support/cas-server-support-events-couchdb/src/test/resources/log4j2-test.xml b/support/cas-server-support-events-couchdb/src/test/resources/log4j2-test.xml deleted file mode 100644 index 7649548c31cc..000000000000 --- a/support/cas-server-support-events-couchdb/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-gauth-couchdb/build.gradle b/support/cas-server-support-gauth-couchdb/build.gradle deleted file mode 100644 index 5a78eaadddcc..000000000000 --- a/support/cas-server-support-gauth-couchdb/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -description = "Apereo CAS Google Authenticator CouchDb" -ext { - publishMetadata = true - projectMetadata = [ - category: "Google Authenticator Multifactor Authentication", - title: "Google Authenticator Support via Apache CouchDb" - ] -} -dependencies { - implementation project(":support:cas-server-support-gauth") - implementation project(":support:cas-server-support-gauth-core") - implementation project(":support:cas-server-support-gauth-core-mfa") - implementation project(":support:cas-server-support-otp-mfa") - implementation project(":support:cas-server-support-otp-mfa-core") - implementation project(":support:cas-server-support-couchdb-core") - - implementation project(":core:cas-server-core-notifications") - implementation project(":core:cas-server-core-authentication-api") - implementation project(":core:cas-server-core-util-api") - implementation project(":core:cas-server-core-configuration-api") - - implementation libraries.ektorp - - testImplementation project(":support:cas-server-support-person-directory") - testImplementation project(":core:cas-server-core") - testImplementation project(":core:cas-server-core-logout-api") - testImplementation project(":core:cas-server-core-logout") - testImplementation project(":core:cas-server-core-cookie") - testImplementation project(":core:cas-server-core-services") - testImplementation project(":core:cas-server-core-tickets") - testImplementation project(":core:cas-server-core-configuration") - testImplementation project(":core:cas-server-core-services-authentication") - testImplementation project(":core:cas-server-core-authentication-mfa") - testImplementation project(":core:cas-server-core-authentication") - testImplementation project(":core:cas-server-core-web") - testImplementation project(":core:cas-server-core-webflow") - testImplementation project(":core:cas-server-core-webflow-mfa") - testImplementation project(":core:cas-server-core-web-api") - testImplementation project(":core:cas-server-core-util") - testImplementation project(":core:cas-server-core-authentication-attributes") - - testImplementation project(path: ":core:cas-server-core-authentication-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-util-api", configuration: "tests") - testImplementation project(path: ":core:cas-server-core-notifications", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-gauth-core", configuration: "tests") - testImplementation project(path: ":support:cas-server-support-gauth", configuration: "tests") -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/config/GoogleAuthenticatorCouchDbConfiguration.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/config/GoogleAuthenticatorCouchDbConfiguration.java deleted file mode 100644 index 7331e5610cc6..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/config/GoogleAuthenticatorCouchDbConfiguration.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.apereo.cas.config; - -import org.apereo.cas.configuration.CasConfigurationProperties; -import org.apereo.cas.configuration.features.CasFeatureModule; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.core.DefaultCouchDbConnectorFactory; -import org.apereo.cas.couchdb.gauth.credential.GoogleAuthenticatorAccountCouchDbRepository; -import org.apereo.cas.couchdb.gauth.token.GoogleAuthenticatorTokenCouchDbRepository; -import org.apereo.cas.gauth.credential.CouchDbGoogleAuthenticatorTokenCredentialRepository; -import org.apereo.cas.gauth.token.GoogleAuthenticatorCouchDbTokenRepository; -import org.apereo.cas.otp.repository.credentials.OneTimeTokenCredentialRepository; -import org.apereo.cas.otp.repository.token.OneTimeTokenRepository; -import org.apereo.cas.util.crypto.CipherExecutor; -import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled; - -import com.warrenstrange.googleauth.IGoogleAuthenticator; -import lombok.val; -import org.ektorp.impl.ObjectMapperFactory; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.scheduling.annotation.EnableScheduling; - -/** - * This is {@link GoogleAuthenticatorCouchDbConfiguration}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.GoogleAuthenticator, module = "couchdb") -@EnableConfigurationProperties(CasConfigurationProperties.class) -@EnableScheduling -@AutoConfiguration -@Deprecated(since = "7.0.0") -public class GoogleAuthenticatorCouchDbConfiguration { - - @ConditionalOnMissingBean(name = "oneTimeTokenAccountCouchDbFactory") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CouchDbConnectorFactory oneTimeTokenAccountCouchDbFactory(final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getAuthn().getMfa().getGauth().getCouchDb(), objectMapperFactory); - } - - @ConditionalOnMissingBean(name = "couchDbGoogleAuthenticatorAccountRegistry") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public OneTimeTokenCredentialRepository googleAuthenticatorAccountRegistry( - @Qualifier("googleAuthenticatorInstance") - final IGoogleAuthenticator googleAuthenticatorInstance, - @Qualifier("googleAuthenticatorAccountCipherExecutor") - final CipherExecutor googleAuthenticatorAccountCipherExecutor, - @Qualifier("googleAuthenticatorScratchCodesCipherExecutor") - final CipherExecutor googleAuthenticatorScratchCodesCipherExecutor, - @Qualifier("couchDbOneTimeTokenAccountRepository") - final GoogleAuthenticatorAccountCouchDbRepository couchDbRepository) { - return new CouchDbGoogleAuthenticatorTokenCredentialRepository(googleAuthenticatorInstance, couchDbRepository, googleAuthenticatorAccountCipherExecutor, - googleAuthenticatorScratchCodesCipherExecutor); - } - - @ConditionalOnMissingBean(name = "couchDbOneTimeTokenAccountRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public GoogleAuthenticatorAccountCouchDbRepository couchDbOneTimeTokenAccountRepository( - @Qualifier("oneTimeTokenAccountCouchDbFactory") - final CouchDbConnectorFactory oneTimeTokenCouchDbFactory, final CasConfigurationProperties casProperties) { - val repository = new GoogleAuthenticatorAccountCouchDbRepository(oneTimeTokenCouchDbFactory.getCouchDbConnector(), - casProperties.getAuthn().getMfa().getGauth().getCouchDb().isCreateIfNotExists()); - repository.initStandardDesignDocument(); - return repository; - } - - @ConditionalOnMissingBean(name = "couchDbOneTimeTokenAutneticatorTokenRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public OneTimeTokenRepository oneTimeTokenAuthenticatorTokenRepository( - @Qualifier("couchDbOneTimeTokenRepository") - final GoogleAuthenticatorTokenCouchDbRepository couchDbOneTimeTokenRepository, final CasConfigurationProperties casProperties) { - return new GoogleAuthenticatorCouchDbTokenRepository(couchDbOneTimeTokenRepository, casProperties.getAuthn().getMfa().getGauth().getCore().getTimeStepSize()); - } - - @ConditionalOnMissingBean(name = "oneTimeTokenCouchDbFactory") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public CouchDbConnectorFactory oneTimeTokenCouchDbFactory(final CasConfigurationProperties casProperties, - @Qualifier("defaultObjectMapperFactory") - final ObjectMapperFactory objectMapperFactory) { - return new DefaultCouchDbConnectorFactory(casProperties.getAuthn().getMfa().getGauth().getCouchDb(), objectMapperFactory); - } - - @ConditionalOnMissingBean(name = "couchDbbOneTimeTokenRepository") - @Bean - @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) - public GoogleAuthenticatorTokenCouchDbRepository couchDbOneTimeTokenRepository( - @Qualifier("oneTimeTokenAccountCouchDbFactory") - final CouchDbConnectorFactory oneTimeTokenCouchDbFactory, final CasConfigurationProperties casProperties) { - return new GoogleAuthenticatorTokenCouchDbRepository(oneTimeTokenCouchDbFactory.getCouchDbConnector(), - casProperties.getAuthn().getMfa().getGauth().getCouchDb().isCreateIfNotExists()); - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/CouchDbGoogleAuthenticatorAccount.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/CouchDbGoogleAuthenticatorAccount.java deleted file mode 100644 index 1f3a47fb208a..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/CouchDbGoogleAuthenticatorAccount.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.apereo.cas.couchdb.gauth.credential; - -import org.apereo.cas.authentication.OneTimeTokenAccount; -import org.apereo.cas.gauth.credential.GoogleAuthenticatorAccount; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.experimental.Accessors; -import lombok.experimental.SuperBuilder; -import lombok.val; - -import java.io.Serial; - -/** - * This is {@link CouchDbGoogleAuthenticatorAccount}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@Setter -@SuperBuilder -@NoArgsConstructor -@Accessors(chain = true) -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) -@Deprecated(since = "7.0.0") -public class CouchDbGoogleAuthenticatorAccount extends GoogleAuthenticatorAccount { - - @Serial - private static final long serialVersionUID = -4286976777933886751L; - - @JsonProperty("_id") - private String cid; - - @JsonProperty("_rev") - private String rev; - - /** - * From. - * - * @param acct the acct - * @return the couch db google authenticator account - */ - public static CouchDbGoogleAuthenticatorAccount from(final OneTimeTokenAccount acct) { - val account = CouchDbGoogleAuthenticatorAccount.builder() - .id(acct.getId()) - .name(acct.getName()) - .username(acct.getUsername().trim().toLowerCase()) - .secretKey(acct.getSecretKey()) - .validationCode(acct.getValidationCode()) - .scratchCodes(acct.getScratchCodes()) - .registrationDate(acct.getRegistrationDate()) - .build(); - - if (acct instanceof CouchDbGoogleAuthenticatorAccount gAcct) { - return account.setCid(gAcct.getCid()).setRev(gAcct.getRev()); - } - return account; - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/GoogleAuthenticatorAccountCouchDbRepository.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/GoogleAuthenticatorAccountCouchDbRepository.java deleted file mode 100644 index daf4da0fdca1..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/credential/GoogleAuthenticatorAccountCouchDbRepository.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.apereo.cas.couchdb.gauth.credential; - -import org.apereo.cas.authentication.OneTimeTokenAccount; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.ektorp.ComplexKey; -import org.ektorp.CouchDbConnector; -import org.ektorp.DocumentNotFoundException; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.UpdateHandler; -import org.ektorp.support.View; - -import java.util.ArrayList; -import java.util.List; - -/** - * This is {@link GoogleAuthenticatorAccountCouchDbRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@View(name = "all", map = "function(doc) { if(doc.secretKey) { emit(doc._id, doc) } }") -@Slf4j -@Deprecated(since = "7.0.0") -public class GoogleAuthenticatorAccountCouchDbRepository extends CouchDbRepositorySupport { - - public GoogleAuthenticatorAccountCouchDbRepository(final CouchDbConnector db, final boolean createIfNotExists) { - super(CouchDbGoogleAuthenticatorAccount.class, db, createIfNotExists); - } - - /** - * Find first account for user. - * - * @param username username for lookup - * @return first one time token account for user - */ - @View(name = "by_username", map = "function(doc) { if(doc.secretKey) { emit(doc.username, doc) } }") - public List findByUsername(final String username) { - try { - return queryView("by_username", username.trim().toLowerCase()); - } catch (final DocumentNotFoundException e) { - LOGGER.trace(e.getMessage(), e); - } - return new ArrayList<>(0); - } - - /** - * Delete token without revision checks. - * - * @param token token to delete - */ - @UpdateHandler(name = "delete_token_account", file = "CouchDbOneTimeTokenAccount_delete.js") - public void deleteTokenAccount(final CouchDbGoogleAuthenticatorAccount token) { - db.callUpdateHandler(stdDesignDocumentId, "delete_token_account", token.getCid(), null); - } - - /** - * Total token accounts in database. - * - * @return count of accounts - */ - @View(name = "count", map = "function(doc) { if(doc.secretKey) { emit(doc._id, doc) } }", reduce = "_count") - public long count() { - val rows = db.queryView(createQuery("count")).getRows(); - return rows.isEmpty() ? 0 : rows.get(0).getValueAsInt(); - } - - /** - * Count devices per user. - * - * @param username the username - * @return the count - */ - @View(name = "count_by_username", map = "function(doc) { if(doc.secretKey) { emit(doc.username, doc._id, doc) } }", reduce = "_count") - public long count(final String username) { - val rows = db.queryView(createQuery("count_by_username").key(username.trim().toLowerCase())).getRows(); - return rows.isEmpty() ? 0 : rows.get(0).getValueAsInt(); - } - - /** - * Find by id one time token account. - * - * @param id the id - * @return the one time token account - */ - @View(name = "by_id", map = "function(doc) { if(doc.secretKey) { emit(doc.id, doc) } }") - public OneTimeTokenAccount findById(final long id) { - val view = createQuery("by_id").key(id).limit(1); - return db.queryView(view, CouchDbGoogleAuthenticatorAccount.class).stream().findFirst().orElse(null); - } - - /** - * Find by id and username one time token account. - * - * @param id the id - * @param username the username - * @return the one time token account - */ - @View(name = "by_id_username", map = "function(doc) { emit([doc.id, doc.username], doc) }") - public OneTimeTokenAccount findByIdAndUsername(final long id, final String username) { - try { - val view = createQuery("by_id_username").key(ComplexKey.of(id, username.trim().toLowerCase())).limit(1); - return db.queryView(view, CouchDbGoogleAuthenticatorAccount.class).stream().findFirst().orElse(null); - } catch (final DocumentNotFoundException e) { - LOGGER.trace(e.getMessage(), e); - } - return null; - } - - -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/CouchDbGoogleAuthenticatorToken.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/CouchDbGoogleAuthenticatorToken.java deleted file mode 100644 index 2da2a2006fda..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/CouchDbGoogleAuthenticatorToken.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.apereo.cas.couchdb.gauth.token; - -import org.apereo.cas.authentication.OneTimeToken; -import org.apereo.cas.gauth.token.GoogleAuthenticatorToken; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; - -import java.io.Serial; -import java.time.LocalDateTime; - -/** - * This is {@link CouchDbGoogleAuthenticatorToken}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Getter -@Setter -@Deprecated(since = "7.0.0") -public class CouchDbGoogleAuthenticatorToken extends GoogleAuthenticatorToken { - - @Serial - private static final long serialVersionUID = 2768980948846869252L; - - @JsonProperty("_id") - private String cid; - - @JsonProperty("_rev") - private String rev; - - @JsonCreator - public CouchDbGoogleAuthenticatorToken(@JsonProperty("_id") final String cid, - @JsonProperty("_rev") final String rev, - @JsonProperty("id") final long id, - @JsonProperty("token") final @NonNull Integer token, - @JsonProperty("userId") final @NonNull String userId, - @JsonProperty("issuedDateTime") final LocalDateTime issuedDateTime - ) { - super(token, userId); - this.cid = cid; - this.rev = rev; - setId(id); - setIssuedDateTime(issuedDateTime); - } - - public CouchDbGoogleAuthenticatorToken(final OneTimeToken oneTimeToken) { - setId(oneTimeToken.getId()); - setIssuedDateTime(oneTimeToken.getIssuedDateTime()); - setToken(oneTimeToken.getToken()); - setUserId(oneTimeToken.getUserId().trim().toLowerCase()); - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/GoogleAuthenticatorTokenCouchDbRepository.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/GoogleAuthenticatorTokenCouchDbRepository.java deleted file mode 100644 index f383574dacc9..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/couchdb/gauth/token/GoogleAuthenticatorTokenCouchDbRepository.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.apereo.cas.couchdb.gauth.token; - -import lombok.val; -import org.ektorp.ComplexKey; -import org.ektorp.CouchDbConnector; -import org.ektorp.support.CouchDbRepositorySupport; -import org.ektorp.support.UpdateHandler; -import org.ektorp.support.View; - -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; - -/** - * This is {@link GoogleAuthenticatorTokenCouchDbRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@View(name = "all", map = "function(doc) { if(doc.token && doc.userId) { emit(doc._id, doc) } }") -@Deprecated(since = "7.0.0") -public class GoogleAuthenticatorTokenCouchDbRepository extends CouchDbRepositorySupport { - public GoogleAuthenticatorTokenCouchDbRepository(final CouchDbConnector db, final boolean createIfNotExists) { - super(CouchDbGoogleAuthenticatorToken.class, db, createIfNotExists); - } - - /** - * Find first by uid, otp pair. - * - * @param uid uid to search - * @param otp otp to search - * @return token for uid, otp pair - */ - @View(name = "by_uid_otp", map = "function(doc) { if(doc.token && doc.userId) { emit([doc.userId, doc.token], doc) } }") - public CouchDbGoogleAuthenticatorToken findOneByUidForOtp(final String uid, final Integer otp) { - val view = createQuery("by_uid_otp").key(ComplexKey.of(uid.trim().toLowerCase(), otp)).limit(1); - return db.queryView(view, CouchDbGoogleAuthenticatorToken.class).stream().findFirst().orElse(null); - } - - /** - * Find by issued date. - * - * @param localDateTime time to search for tokens before - * @return tokens issued before given date - */ - @View(name = "by_issued_date_time", map = "function(doc) { if(doc.token && doc.userId) { emit(doc.issuedDateTime, doc) } }") - public Collection findByIssuedDateTimeBefore(final LocalDateTime localDateTime) { - val view = createQuery("by_issued_date_time").endKey(localDateTime); - return db.queryView(view, CouchDbGoogleAuthenticatorToken.class); - } - - /** - * Find tokens by user id. - * - * @param userId user id to search for - * @return tokens belonging to use id - */ - @View(name = "by_userId", map = "function(doc) { if(doc.token && doc.userId) { emit(doc.userId, doc) } }") - public List findByUserId(final String userId) { - return queryView("by_userId", userId.trim().toLowerCase()); - } - - /** - * Token count for a user. - * - * @param userId user to count tokens for - * @return count of the user's tokens - */ - @View(name = "count_by_userId", map = "function(doc) { if(doc.token && doc.userId) { emit(doc.userId, doc) } }", reduce = "_count") - public long countByUserId(final String userId) { - val view = createQuery("count_by_userId").key(userId.trim().toLowerCase()); - val rows = db.queryView(view).getRows(); - if (rows.isEmpty()) { - return 0; - } - return rows.get(0).getValueAsInt(); - } - - /** - * Total number of tokens stored. - * - * @return number of tokens in database - */ - @View(name = "count", map = "function(doc) { if(doc.token && doc.userId) { emit(doc._id, doc) } }", reduce = "_count") - public long count() { - val rows = db.queryView(createQuery("count")).getRows(); - if (rows.isEmpty()) { - return 0; - } - return rows.get(0).getValueAsInt(); - } - - /** - * Delete record, ignoring rev. - * - * @param token token to delete - */ - @UpdateHandler(name = "delete_token", file = "CouchDbOneTimeToken_delete.js") - public void deleteToken(final CouchDbGoogleAuthenticatorToken token) { - db.callUpdateHandler(stdDesignDocumentId, "delete_token", token.getCid(), null); - } - - - /** - * Find all by uid, otp pair. - * - * @param uid uid to search - * @param otp otp to search - * @return token for uid, otp pair - */ - @View(name = "by_uid_otp", map = "function(doc) { if(doc.token && doc.userId) { emit([doc.userId, doc.token], doc) } }") - public List findByUidForOtp(final String uid, final Integer otp) { - val view = createQuery("by_uid_otp").key(ComplexKey.of(uid.trim().toLowerCase(), otp)); - return db.queryView(view, CouchDbGoogleAuthenticatorToken.class); - } - - /** - * Find by token. - * - * @param otp token to search for - * @return token for the otp - */ - @View(name = "by_token", map = "function(doc) { if(doc.token && doc.userId) { emit(doc.token, doc) } }") - public List findByToken(final Integer otp) { - return queryView("by_token", otp); - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepository.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepository.java deleted file mode 100644 index 96633b6533d4..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepository.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.apereo.cas.gauth.credential; - -import org.apereo.cas.authentication.OneTimeTokenAccount; -import org.apereo.cas.couchdb.gauth.credential.CouchDbGoogleAuthenticatorAccount; -import org.apereo.cas.couchdb.gauth.credential.GoogleAuthenticatorAccountCouchDbRepository; -import org.apereo.cas.util.crypto.CipherExecutor; - -import com.warrenstrange.googleauth.IGoogleAuthenticator; -import lombok.extern.slf4j.Slf4j; -import lombok.val; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * This is {@link CouchDbGoogleAuthenticatorTokenCredentialRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Slf4j -@Deprecated(since = "7.0.0") -public class CouchDbGoogleAuthenticatorTokenCredentialRepository extends BaseGoogleAuthenticatorTokenCredentialRepository { - private final GoogleAuthenticatorAccountCouchDbRepository couchDbRepository; - - public CouchDbGoogleAuthenticatorTokenCredentialRepository(final IGoogleAuthenticator googleAuthenticator, - final GoogleAuthenticatorAccountCouchDbRepository couchDbRepository, - final CipherExecutor tokenCredentialCipher, - final CipherExecutor scratchCodesCipher) { - super(tokenCredentialCipher, scratchCodesCipher, googleAuthenticator); - this.couchDbRepository = couchDbRepository; - } - - @Override - public OneTimeTokenAccount get(final String username, final long id) { - return this.couchDbRepository.findByIdAndUsername(id, username); - } - - @Override - public OneTimeTokenAccount get(final long id) { - return this.couchDbRepository.findById(id); - } - - @Override - public Collection get(final String username) { - val accounts = couchDbRepository.findByUsername(username); - if (accounts == null || accounts.isEmpty()) { - LOGGER.debug("No record could be found for google authenticator id [{}]", username); - return new ArrayList<>(0); - } - return decode(accounts); - } - - @Override - public Collection load() { - return couchDbRepository.getAll(); - } - - @Override - public OneTimeTokenAccount save(final OneTimeTokenAccount account) { - return update(account); - } - - @Override - public OneTimeTokenAccount update(final OneTimeTokenAccount account) { - val records = couchDbRepository.findByUsername(account.getUsername()); - if (records == null || records.isEmpty()) { - val newAccount = CouchDbGoogleAuthenticatorAccount.from(encode(account)); - couchDbRepository.add(newAccount); - return newAccount; - } - records.stream() - .filter(rec -> rec.getId() == account.getId()) - .map(CouchDbGoogleAuthenticatorAccount.class::cast) - .findFirst() - .ifPresent(act -> couchDbRepository.update(CouchDbGoogleAuthenticatorAccount.from(account))); - return account; - } - - @Override - public void deleteAll() { - couchDbRepository.getAll().forEach(couchDbRepository::deleteTokenAccount); - } - - @Override - public void delete(final String username) { - couchDbRepository.findByUsername(username).forEach(couchDbRepository::deleteTokenAccount); - } - - @Override - public void delete(final long id) { - val entity = (CouchDbGoogleAuthenticatorAccount) couchDbRepository.findById(id); - couchDbRepository.deleteTokenAccount(entity); - } - - @Override - public long count() { - return couchDbRepository.count(); - } - - @Override - public long count(final String username) { - return couchDbRepository.count(username); - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepository.java b/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepository.java deleted file mode 100644 index e5afdc46b603..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepository.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.apereo.cas.gauth.token; - -import org.apereo.cas.couchdb.gauth.token.CouchDbGoogleAuthenticatorToken; -import org.apereo.cas.couchdb.gauth.token.GoogleAuthenticatorTokenCouchDbRepository; -import org.apereo.cas.otp.repository.token.BaseOneTimeTokenRepository; -import org.apereo.cas.util.LoggingUtils; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.ektorp.UpdateConflictException; - -import java.time.LocalDateTime; -import java.time.ZoneId; - -/** - * This is {@link GoogleAuthenticatorCouchDbTokenRepository}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Slf4j -@RequiredArgsConstructor -@Deprecated(since = "7.0.0") -public class GoogleAuthenticatorCouchDbTokenRepository extends BaseOneTimeTokenRepository { - - private final GoogleAuthenticatorTokenCouchDbRepository couchDb; - private final long expireTokensInSeconds; - - @Override - public void store(final GoogleAuthenticatorToken token) { - couchDb.add(new CouchDbGoogleAuthenticatorToken(token)); - } - - @Override - public GoogleAuthenticatorToken get(final String uid, final Integer otp) { - return couchDb.findOneByUidForOtp(uid, otp); - } - - @Override - public void remove(final String uid, final Integer otp) { - couchDb.findByUidForOtp(uid, otp).forEach(couchDb::deleteToken); - } - - @Override - public void remove(final String uid) { - couchDb.findByUserId(uid).forEach(couchDb::deleteToken); - } - - @Override - public void remove(final Integer otp) { - couchDb.findByToken(otp).forEach(couchDb::deleteToken); - } - - @Override - public void removeAll() { - couchDb.getAll().forEach(couchDb::deleteToken); - } - - @Override - public long count(final String uid) { - return couchDb.countByUserId(uid); - } - - @Override - public long count() { - return couchDb.count(); - } - - @Override - protected void cleanInternal() { - try { - val since = LocalDateTime.now(ZoneId.systemDefault()).minusSeconds(expireTokensInSeconds); - LOGGER.debug("Removing tokens older than [{}]", since); - couchDb.findByIssuedDateTimeBefore(since).forEach(couchDb::remove); - } catch (final UpdateConflictException e) { - LoggingUtils.warn(LOGGER, e); - } - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/support/cas-server-support-gauth-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index e94f8b498c71..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.apereo.cas.config.GoogleAuthenticatorCouchDbConfiguration diff --git a/support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/credential/CouchDbOneTimeTokenAccount_delete.js b/support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/credential/CouchDbOneTimeTokenAccount_delete.js deleted file mode 100644 index 0488fb2d3240..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/credential/CouchDbOneTimeTokenAccount_delete.js +++ /dev/null @@ -1,8 +0,0 @@ -function(doc, req){ - if (!doc){ - return [null, "No record supplied."] - } else { - doc['_deleted'] = true - return [doc, "Record Deleted."] - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/token/CouchDbOneTimeToken_delete.js b/support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/token/CouchDbOneTimeToken_delete.js deleted file mode 100644 index 0488fb2d3240..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/main/resources/org/apereo/cas/couchdb/gauth/token/CouchDbOneTimeToken_delete.js +++ /dev/null @@ -1,8 +0,0 @@ -function(doc, req){ - if (!doc){ - return [null, "No record supplied."] - } else { - doc['_deleted'] = true - return [doc, "Record Deleted."] - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java b/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java deleted file mode 100644 index 56557599bd9b..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/AllTestsSuite.java +++ /dev/null @@ -1,22 +0,0 @@ - -package org.apereo.cas; - -import org.apereo.cas.gauth.credential.CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests; -import org.apereo.cas.gauth.token.GoogleAuthenticatorCouchDbTokenRepositoryTests; - -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; - -/** - * This is {@link AllTestsSuite}. - * - * @author Misagh Moayyed - * @since 6.0.0-RC3 - */ -@SelectClasses({ - GoogleAuthenticatorCouchDbTokenRepositoryTests.class, - CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests.class -}) -@Suite -public class AllTestsSuite { -} diff --git a/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests.java b/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests.java deleted file mode 100644 index 2da8621f0755..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/credential/CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apereo.cas.gauth.credential; - -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.GoogleAuthenticatorCouchDbConfiguration; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.gauth.credential.GoogleAuthenticatorAccountCouchDbRepository; -import org.apereo.cas.otp.repository.credentials.OneTimeTokenCredentialRepository; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; - -import lombok.Getter; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; - -/** - * This is {@link CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Tag("CouchDb") -@SpringBootTest(classes = { - CasCouchDbCoreConfiguration.class, - GoogleAuthenticatorCouchDbConfiguration.class, - BaseOneTimeTokenCredentialRepositoryTests.SharedTestConfiguration.class -}, - properties = { - "cas.authn.mfa.gauth.crypto.enabled=false", - "cas.authn.mfa.gauth.couch-db.username=cas", - "cas.authn.mfa.gauth.couch-db.caching=false", - "cas.authn.mfa.gauth.couch-db.db-name=gauth_credential", - "cas.authn.mfa.gauth.couch-db.password=password" - }) -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class CouchDbGoogleAuthenticatorTokenCredentialRepositoryTests extends BaseOneTimeTokenCredentialRepositoryTests { - - @Autowired - @Qualifier("oneTimeTokenAccountCouchDbFactory") - private CouchDbConnectorFactory couchDbFactory; - - @Autowired - @Qualifier("googleAuthenticatorAccountRegistry") - private OneTimeTokenCredentialRepository registry; - - @Autowired - @Qualifier("couchDbOneTimeTokenAccountRepository") - private GoogleAuthenticatorAccountCouchDbRepository couchDbRepository; - - @BeforeEach - @Override - public void initialize() { - couchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(couchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initStandardDesignDocument(); - registry.deleteAll(); - super.initialize(); - } - - @AfterEach - @Override - public void afterEach() { - super.afterEach(); - registry.deleteAll(); - couchDbFactory.getCouchDbInstance().deleteDatabase(couchDbFactory.getCouchDbConnector().getDatabaseName()); - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepositoryTests.java b/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepositoryTests.java deleted file mode 100644 index 411e10205d5d..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/test/java/org/apereo/cas/gauth/token/GoogleAuthenticatorCouchDbTokenRepositoryTests.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.apereo.cas.gauth.token; - -import org.apereo.cas.config.CasCoreAuthenticationConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationHandlersConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationMetadataConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationPolicyConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationPrincipalConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationServiceSelectionStrategyConfiguration; -import org.apereo.cas.config.CasCoreAuthenticationSupportConfiguration; -import org.apereo.cas.config.CasCoreConfiguration; -import org.apereo.cas.config.CasCoreHttpConfiguration; -import org.apereo.cas.config.CasCoreMultifactorAuthenticationConfiguration; -import org.apereo.cas.config.CasCoreNotificationsConfiguration; -import org.apereo.cas.config.CasCoreServicesAuthenticationConfiguration; -import org.apereo.cas.config.CasCoreServicesConfiguration; -import org.apereo.cas.config.CasCoreTicketCatalogConfiguration; -import org.apereo.cas.config.CasCoreTicketIdGeneratorsConfiguration; -import org.apereo.cas.config.CasCoreTicketsConfiguration; -import org.apereo.cas.config.CasCoreTicketsSerializationConfiguration; -import org.apereo.cas.config.CasCoreUtilConfiguration; -import org.apereo.cas.config.CasCoreWebConfiguration; -import org.apereo.cas.config.CasCouchDbCoreConfiguration; -import org.apereo.cas.config.CasPersonDirectoryConfiguration; -import org.apereo.cas.config.GoogleAuthenticatorCouchDbConfiguration; -import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration; -import org.apereo.cas.config.support.authentication.GoogleAuthenticatorAuthenticationEventExecutionPlanConfiguration; -import org.apereo.cas.config.support.authentication.GoogleAuthenticatorAuthenticationMultifactorProviderBypassConfiguration; -import org.apereo.cas.couchdb.core.CouchDbConnectorFactory; -import org.apereo.cas.couchdb.gauth.token.GoogleAuthenticatorTokenCouchDbRepository; -import org.apereo.cas.logout.config.CasCoreLogoutConfiguration; -import org.apereo.cas.util.junit.EnabledIfListeningOnPort; -import org.apereo.cas.web.config.CasCookieConfiguration; -import org.apereo.cas.web.flow.config.CasCoreWebflowConfiguration; -import org.apereo.cas.web.flow.config.CasMultifactorAuthenticationWebflowConfiguration; -import org.apereo.cas.web.flow.config.CasWebflowContextConfiguration; - -import lombok.Getter; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.scheduling.annotation.EnableScheduling; - -/** - * This is {@link GoogleAuthenticatorCouchDbTokenRepositoryTests}. - * - * @author Timur Duehr - * @since 6.0.0 - * @deprecated Since 7 - */ -@Tag("CouchDb") -@SpringBootTest(classes = { - CasCouchDbCoreConfiguration.class, - GoogleAuthenticatorCouchDbConfiguration.class, - GoogleAuthenticatorAuthenticationMultifactorProviderBypassConfiguration.class, - CasWebflowContextConfiguration.class, - CasCoreWebflowConfiguration.class, - CasCoreMultifactorAuthenticationConfiguration.class, - CasMultifactorAuthenticationWebflowConfiguration.class, - CasCoreTicketsConfiguration.class, - CasCoreTicketIdGeneratorsConfiguration.class, - CasCoreTicketCatalogConfiguration.class, - CasCoreTicketsSerializationConfiguration.class, - CasCoreLogoutConfiguration.class, - CasCoreHttpConfiguration.class, - CasCoreNotificationsConfiguration.class, - CasCoreServicesConfiguration.class, - CasWebApplicationServiceFactoryConfiguration.class, - CasCoreAuthenticationConfiguration.class, - CasCoreServicesAuthenticationConfiguration.class, - CasCoreAuthenticationMetadataConfiguration.class, - CasCoreAuthenticationPolicyConfiguration.class, - CasCoreAuthenticationPrincipalConfiguration.class, - CasCoreAuthenticationHandlersConfiguration.class, - CasCoreAuthenticationSupportConfiguration.class, - CasPersonDirectoryConfiguration.class, - GoogleAuthenticatorAuthenticationEventExecutionPlanConfiguration.class, - AopAutoConfiguration.class, - WebMvcAutoConfiguration.class, - CasCoreConfiguration.class, - CasCookieConfiguration.class, - CasCoreAuthenticationServiceSelectionStrategyConfiguration.class, - CasCoreUtilConfiguration.class, - RefreshAutoConfiguration.class, - CasCoreWebConfiguration.class -}, - properties = { - "cas.authn.mfa.gauth.crypto.enabled=false", - "cas.authn.mfa.gauth.couch-db.dbName=gauth_token", - "cas.authn.mfa.gauth.couch-db.username=cas", - "cas.authn.mfa.gauth.couch-db.password=password" - }) -@EnableAspectJAutoProxy(proxyTargetClass = false) -@EnableScheduling -@Getter -@EnabledIfListeningOnPort(port = 5984) -@Deprecated(since = "7.0.0") -public class GoogleAuthenticatorCouchDbTokenRepositoryTests extends BaseOneTimeTokenRepositoryTests { - - @Autowired - @Qualifier("oneTimeTokenCouchDbFactory") - private CouchDbConnectorFactory couchDbFactory; - - @Autowired - @Qualifier("couchDbOneTimeTokenRepository") - private GoogleAuthenticatorTokenCouchDbRepository couchDbRepository; - - @BeforeEach - @Override - public void initialize() { - couchDbFactory.getCouchDbInstance().createDatabaseIfNotExists(couchDbFactory.getCouchDbConnector().getDatabaseName()); - couchDbRepository.initStandardDesignDocument(); - super.initialize(); - } -} diff --git a/support/cas-server-support-gauth-couchdb/src/test/resources/log4j2-test.xml b/support/cas-server-support-gauth-couchdb/src/test/resources/log4j2-test.xml deleted file mode 100644 index 518c83a40164..000000000000 --- a/support/cas-server-support-gauth-couchdb/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java index 2630c85d5086..1a3be4e18201 100644 --- a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java +++ b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java @@ -31,7 +31,8 @@ import java.util.Objects; /** - * CAS RESTful resource for vending STs: + * CAS RESTful resource for vending STs. + * *
    *
  • {@code POST /v1/tickets/{TGT-id}}
  • *
diff --git a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java index 91738c5fa400..829c1f7f6456 100644 --- a/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java +++ b/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/TicketGrantingTicketResource.java @@ -33,7 +33,7 @@ import java.util.List; /** - * CAS RESTful resource for vending and deleting TGTs: + * CAS RESTful resource for vending and deleting TGTs. *