All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dk.cloudcreate.essentials.components.distributed.fencedlock.postgresql.PostgresqlFencedLockManager Maven / Gradle / Ivy

Go to download

This library focuses on providing a distributed fenced locking mechanism based on postgresql

There is a newer version: 0.40.19
Show newest version
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dk.cloudcreate.essentials.components.distributed.fencedlock.postgresql;

import dk.cloudcreate.essentials.components.foundation.IOExceptionUtil;
import dk.cloudcreate.essentials.components.foundation.fencedlock.*;
import dk.cloudcreate.essentials.components.foundation.postgresql.PostgresqlUtil;
import dk.cloudcreate.essentials.components.foundation.transaction.UnitOfWork;
import dk.cloudcreate.essentials.components.foundation.transaction.jdbi.*;
import dk.cloudcreate.essentials.reactive.*;
import org.jdbi.v3.core.Jdbi;

import java.time.*;
import java.util.Optional;

/**
 * Provides a {@link FencedLockManager} implementation using Postgresql to coordinate intra-service distributed locks
*
* Security:
* To support customization of storage table name, the {@code fencedLocksTableName} will be directly used in constructing SQL statements * through string concatenation, which exposes the component to SQL injection attacks.
*
* Security Note:
* It is the responsibility of the user of this component to sanitize the {@code fencedLocksTableName} * to ensure the security of all the SQL statements generated by this component. The {@link PostgresqlFencedLockStorage} component will * call the {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} method to validate the table name as a first line of defense.
* The {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} provides an initial layer of defense against SQL injection by applying naming conventions intended to reduce the risk of malicious input.
* However, Essentials components as well as {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} does not offer exhaustive protection, nor does it assure the complete security of the resulting SQL against SQL injection threats.
* The responsibility for implementing protective measures against SQL Injection lies exclusively with the users/developers using the Essentials components and its supporting classes.
* Users must ensure thorough sanitization and validation of API input parameters, column, table, and index names.
* Insufficient attention to these practices may leave the application vulnerable to SQL injection, potentially endangering the security and integrity of the database.
*
* It is highly recommended that the {@code fencedLocksTableName} value is only derived from a controlled and trusted source.
* To mitigate the risk of SQL injection attacks, external or untrusted inputs should never directly provide the {@code fencedLocksTableName} value.
* Failure to adequately sanitize and validate this value could expose the application to SQL injection * vulnerabilities, compromising the security and integrity of the database. */ public final class PostgresqlFencedLockManager extends DBFencedLockManager { /** * Security:
* To support customization of storage table name, the {@code fencedLocksTableName} will be directly used in constructing SQL statements * through string concatenation, which exposes the component to SQL injection attacks.
*
* Security Note:
* It is the responsibility of the user of this component to sanitize the {@code fencedLocksTableName} * to ensure the security of all the SQL statements generated by this component. The {@link PostgresqlFencedLockStorage} component will * call the {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} method to validate the table name as a first line of defense.
* The {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} provides an initial layer of defense against SQL injection by applying naming conventions intended to reduce the risk of malicious input.
* However, Essentials components as well as {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} does not offer exhaustive protection, nor does it assure the complete security of the resulting SQL against SQL injection threats.
* The responsibility for implementing protective measures against SQL Injection lies exclusively with the users/developers using the Essentials components and its supporting classes.
* Users must ensure thorough sanitization and validation of API input parameters, column, table, and index names.
* Insufficient attention to these practices may leave the application vulnerable to SQL injection, potentially endangering the security and integrity of the database.
*
* It is highly recommended that the {@code fencedLocksTableName} value is only derived from a controlled and trusted source.
* To mitigate the risk of SQL injection attacks, external or untrusted inputs should never directly provide the {@code fencedLocksTableName} value.
* Failure to adequately sanitize and validate this value could expose the application to SQL injection * vulnerabilities, compromising the security and integrity of the database. * * @return a new builder */ public static PostgresqlFencedLockManagerBuilder builder() { return new PostgresqlFencedLockManagerBuilder(); } /** * @param jdbi the jdbi instance * @param unitOfWorkFactory The unit of work factory * @param lockManagerInstanceId The unique name for this lock manager instance. If left {@link Optional#empty()} then the machines hostname is used * @param fencedLocksTableName the name of the table where the fenced locks will be stored
* Note:
* To support customization of storage table name, the {@code fencedLocksTableName} will be directly used in constructing SQL statements * through string concatenation, which exposes the component to SQL injection attacks.
*
* Security Note:
* It is the responsibility of the user of this component to sanitize the {@code fencedLocksTableName} * to ensure the security of all the SQL statements generated by this component. The {@link PostgresqlFencedLockStorage} component will * call the {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} method to validate the table name as a first line of defense.
* The {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} provides an initial layer of defense against SQL injection by applying naming conventions intended to reduce the risk of malicious input.
* However, Essentials components as well as {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} does not offer exhaustive protection, nor does it assure the complete security of the resulting SQL against SQL injection threats.
* The responsibility for implementing protective measures against SQL Injection lies exclusively with the users/developers using the Essentials components and its supporting classes.
* Users must ensure thorough sanitization and validation of API input parameters, column, table, and index names.
* Insufficient attention to these practices may leave the application vulnerable to SQL injection, potentially endangering the security and integrity of the database.
*
* It is highly recommended that the {@code fencedLocksTableName} value is only derived from a controlled and trusted source.
* To mitigate the risk of SQL injection attacks, external or untrusted inputs should never directly provide the {@code fencedLocksTableName} value.
* Failure to adequately sanitize and validate this value could expose the application to SQL injection * vulnerabilities, compromising the security and integrity of the database. * @param lockTimeOut the period between {@link FencedLock#getLockLastConfirmedTimestamp()} and the current time before the lock is marked as timed out * @param lockConfirmationInterval how often should the locks be confirmed. MUST is less than the lockTimeOut * @param releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation Should {@link FencedLock}'s acquired by this {@link FencedLockManager} be released in case calls to {@link FencedLockStorage#confirmLockInDB(DBFencedLockManager, UnitOfWork, DBFencedLock, OffsetDateTime)} fails * with an exception where {@link IOExceptionUtil#isIOException(Throwable)} returns true - * If releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation is true, then {@link FencedLock}'s will be released locally, * otherwise we will retain the {@link FencedLock}'s as locked. */ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public PostgresqlFencedLockManager(Jdbi jdbi, HandleAwareUnitOfWorkFactory unitOfWorkFactory, Optional lockManagerInstanceId, String fencedLocksTableName, Duration lockTimeOut, Duration lockConfirmationInterval, boolean releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation) { super(new PostgresqlFencedLockStorage(jdbi, fencedLocksTableName), unitOfWorkFactory, lockManagerInstanceId, lockTimeOut, lockConfirmationInterval, releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation, Optional.empty() ); } /** * @param jdbi the jdbi instance * @param unitOfWorkFactory The unit of work factory * @param lockManagerInstanceId The unique name for this lock manager instance. If left {@link Optional#empty()} then the machines hostname is used * @param fencedLocksTableName the name of the table where the fenced locks will be stored
* Note:
* To support customization of storage table name, the {@code fencedLocksTableName} will be directly used in constructing SQL statements * through string concatenation, which exposes the component to SQL injection attacks.
*
* Security Note:
* It is the responsibility of the user of this component to sanitize the {@code fencedLocksTableName} * to ensure the security of all the SQL statements generated by this component. The {@link PostgresqlFencedLockStorage} component will * call the {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} method to validate the table name as a first line of defense.
* The {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} provides an initial layer of defense against SQL injection by applying naming conventions intended to reduce the risk of malicious input.
* However, Essentials components as well as {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} does not offer exhaustive protection, nor does it assure the complete security of the resulting SQL against SQL injection threats.
* The responsibility for implementing protective measures against SQL Injection lies exclusively with the users/developers using the Essentials components and its supporting classes.
* Users must ensure thorough sanitization and validation of API input parameters, column, table, and index names.
* Insufficient attention to these practices may leave the application vulnerable to SQL injection, potentially endangering the security and integrity of the database.
*
* It is highly recommended that the {@code fencedLocksTableName} value is only derived from a controlled and trusted source.
* To mitigate the risk of SQL injection attacks, external or untrusted inputs should never directly provide the {@code fencedLocksTableName} value.
* Failure to adequately sanitize and validate this value could expose the application to SQL injection * vulnerabilities, compromising the security and integrity of the database. * @param lockTimeOut the period between {@link FencedLock#getLockLastConfirmedTimestamp()} and the current time before the lock is marked as timed out * @param lockConfirmationInterval how often should the locks be confirmed. MUST is less than the lockTimeOut * @param releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation Should {@link FencedLock}'s acquired by this {@link FencedLockManager} be released in case calls to {@link FencedLockStorage#confirmLockInDB(DBFencedLockManager, UnitOfWork, DBFencedLock, OffsetDateTime)} fails * with an exception where {@link IOExceptionUtil#isIOException(Throwable)} returns true - * If releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation is true, then {@link FencedLock}'s will be released locally, * otherwise we will retain the {@link FencedLock}'s as locked. * @param eventBus optional {@link LocalEventBus} where {@link FencedLockEvents} will be published */ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public PostgresqlFencedLockManager(Jdbi jdbi, HandleAwareUnitOfWorkFactory unitOfWorkFactory, Optional lockManagerInstanceId, String fencedLocksTableName, Duration lockTimeOut, Duration lockConfirmationInterval, boolean releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation, Optional eventBus) { super(new PostgresqlFencedLockStorage(jdbi, fencedLocksTableName), unitOfWorkFactory, lockManagerInstanceId, lockTimeOut, lockConfirmationInterval, releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation, eventBus ); } /** * Create a {@link PostgresqlFencedLockManager} with the machines hostname as lock manager instance name and the default fenced lock table name ({@link PostgresqlFencedLockStorage#DEFAULT_FENCED_LOCKS_TABLE_NAME}) * * @param jdbi the jdbi instance * @param unitOfWorkFactory The unit of work factory * @param lockTimeOut the period between {@link FencedLock#getLockLastConfirmedTimestamp()} and the current time before the lock is marked as timed out * @param lockConfirmationInterval how often should the locks be confirmed. MUST is less than the lockTimeOut * @param releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation Should {@link FencedLock}'s acquired by this {@link FencedLockManager} be released in case calls to {@link FencedLockStorage#confirmLockInDB(DBFencedLockManager, UnitOfWork, DBFencedLock, OffsetDateTime)} fails * with an exception where {@link IOExceptionUtil#isIOException(Throwable)} returns true - * If releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation is true, then {@link FencedLock}'s will be released locally, * otherwise we will retain the {@link FencedLock}'s as locked. * @param eventBus optional {@link LocalEventBus} where {@link FencedLockEvents} will be published */ public PostgresqlFencedLockManager(Jdbi jdbi, HandleAwareUnitOfWorkFactory unitOfWorkFactory, Duration lockTimeOut, Duration lockConfirmationInterval, boolean releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation, Optional eventBus) { this(jdbi, unitOfWorkFactory, Optional.empty(), PostgresqlFencedLockStorage.DEFAULT_FENCED_LOCKS_TABLE_NAME, lockTimeOut, lockConfirmationInterval, releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation, eventBus ); } /** * Create a {@link PostgresqlFencedLockManager} with the machines hostname as lock manager instance name and the default fenced lock table name ({@link PostgresqlFencedLockStorage#DEFAULT_FENCED_LOCKS_TABLE_NAME}) * * @param jdbi the jdbi instance * @param unitOfWorkFactory The unit of work factory * @param lockManagerInstanceId The unique name for this lock manager instance. If left {@link Optional#empty()} then the machines hostname is used * @param lockTimeOut the period between {@link FencedLock#getLockLastConfirmedTimestamp()} and the current time before the lock is marked as timed out * @param lockConfirmationInterval how often should the locks be confirmed. MUST is less than the lockTimeOut * @param releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation Should {@link FencedLock}'s acquired by this {@link FencedLockManager} be released in case calls to {@link FencedLockStorage#confirmLockInDB(DBFencedLockManager, UnitOfWork, DBFencedLock, OffsetDateTime)} fails * with an exception where {@link IOExceptionUtil#isIOException(Throwable)} returns true - * If releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation is true, then {@link FencedLock}'s will be released locally, * otherwise we will retain the {@link FencedLock}'s as locked. */ public PostgresqlFencedLockManager(Jdbi jdbi, HandleAwareUnitOfWorkFactory unitOfWorkFactory, Optional lockManagerInstanceId, Duration lockTimeOut, Duration lockConfirmationInterval, boolean releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation ) { this(jdbi, unitOfWorkFactory, lockManagerInstanceId, PostgresqlFencedLockStorage.DEFAULT_FENCED_LOCKS_TABLE_NAME, lockTimeOut, lockConfirmationInterval, releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmation, Optional.empty() ); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy