1
0

feature/run-office-module-without-booking-and-hosting (#148)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Co-authored-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
Co-authored-by: Timotheus Pokorra <timotheus.pokorra@solidcharity.com>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/148
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig
2025-01-21 14:36:49 +01:00
parent ad61f2af59
commit c1d3d583e7
91 changed files with 643 additions and 101 deletions
@@ -0,0 +1,105 @@
package net.hostsharing.hsadminng.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.endpoint.SanitizableData;
import org.springframework.boot.actuate.endpoint.SanitizingFunction;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
// HOWTO: exclude sensitive values, like passwords and other secrets, from being show by actuator endpoints:
// either use: add your custom keys to management.endpoint.additionalKeysToSanitize,
// or, if you need more heuristics, amend this code down here.
@Component
public class ActuatorSanitizer implements SanitizingFunction {
private static final String[] REGEX_PARTS = {"*", "$", "^", "+"};
private static final Set<String> DEFAULT_KEYS_TO_SANITIZE = Set.of(
"password", "secret", "token", ".*credentials.*", "vcap_services", "^vcap\\.services.*$", "sun.java.command", "^spring[._]application[._]json$"
);
private static final Set<String> URI_USERINFO_KEYS = Set.of(
"uri", "uris", "url", "urls", "address", "addresses"
);
private static final Pattern URI_USERINFO_PATTERN = Pattern.compile("^\\[?[A-Za-z][A-Za-z0-9\\+\\.\\-]+://.+:(.*)@.+$");
private final List<Pattern> keysToSanitize = new ArrayList<>();
public ActuatorSanitizer(@Value("${management.endpoint.additionalKeysToSanitize:}") final List<String> additionalKeysToSanitize) {
addKeysToSanitize(DEFAULT_KEYS_TO_SANITIZE);
addKeysToSanitize(URI_USERINFO_KEYS);
addKeysToSanitize(additionalKeysToSanitize);
}
@Override
public SanitizableData apply(final SanitizableData data) {
if (data.getValue() == null) {
return data;
}
for (final Pattern pattern : keysToSanitize) {
if (pattern.matcher(data.getKey()).matches()) {
if (keyIsUriWithUserInfo(pattern)) {
return data.withValue(sanitizeUris(data.getValue().toString()));
}
return data.withValue(SanitizableData.SANITIZED_VALUE);
}
}
return data;
}
private void addKeysToSanitize(final Collection<String> keysToSanitize) {
for (final String key : keysToSanitize) {
this.keysToSanitize.add(getPattern(key));
}
}
private Pattern getPattern(final String value) {
if (isRegex(value)) {
return Pattern.compile(value, Pattern.CASE_INSENSITIVE);
}
return Pattern.compile(".*" + value + "$", Pattern.CASE_INSENSITIVE);
}
private boolean isRegex(final String value) {
for (final String part : REGEX_PARTS) {
if (value.contains(part)) {
return true;
}
}
return false;
}
private boolean keyIsUriWithUserInfo(final Pattern pattern) {
for (String uriKey : URI_USERINFO_KEYS) {
if (pattern.matcher(uriKey).matches()) {
return true;
}
}
return false;
}
private Object sanitizeUris(final String value) {
return Arrays.stream(value.split(",")).map(this::sanitizeUri).collect(Collectors.joining(","));
}
private String sanitizeUri(final String value) {
final var matcher = URI_USERINFO_PATTERN.matcher(value);
final var password = matcher.matches() ? matcher.group(1) : null;
if (password != null) {
return StringUtils.replace(value, ":" + password + "@", ":" + SanitizableData.SANITIZED_VALUE + "@");
}
return value;
}
}
@@ -2,12 +2,14 @@ package net.hostsharing.hsadminng.hs.booking.debitor;
import io.micrometer.core.annotation.Timed;
import org.springframework.data.repository.Repository;
import org.springframework.context.annotation.Profile;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public interface HsBookingDebitorRepository extends Repository<HsBookingDebitorEntity, UUID> {
@Profile("!only-office")
public interface HsBookingDebitorRepository extends Repository<HsBookingDebitorEntity, UUID> {
@Timed("app.booking.debitor.repo.findByUuid")
Optional<HsBookingDebitorEntity> findByUuid(UUID id);
@@ -1,10 +1,12 @@
package net.hostsharing.hsadminng.hs.booking.item;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.repository.Repository;
import java.util.UUID;
@Profile("!only-office")
public interface BookingItemCreatedEventRepository extends Repository<BookingItemCreatedEventEntity, UUID> {
@Timed("app.booking.items.repo.save")
@@ -16,6 +16,7 @@ import net.hostsharing.hsadminng.mapper.StrictMapper;
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
@@ -30,6 +31,7 @@ import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
@RestController
@Profile("!only-office")
public class HsBookingItemController implements HsBookingItemsApi {
@Autowired
@@ -1,12 +1,14 @@
package net.hostsharing.hsadminng.hs.booking.item;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsBookingItemRbacRepository extends HsBookingItemRepository<HsBookingItemRbacEntity>,
Repository<HsBookingItemRbacEntity, UUID> {
@@ -1,12 +1,14 @@
package net.hostsharing.hsadminng.hs.booking.item;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsBookingItemRealRepository extends HsBookingItemRepository<HsBookingItemRealEntity>,
Repository<HsBookingItemRealEntity, UUID> {
@@ -1,10 +1,13 @@
package net.hostsharing.hsadminng.hs.booking.item;
import org.springframework.context.annotation.Profile;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsBookingItemRepository<E extends HsBookingItem> {
Optional<E> findByUuid(final UUID bookingItemUuid);
@@ -9,6 +9,7 @@ import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProj
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectResource;
import net.hostsharing.hsadminng.mapper.StrictMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
@@ -20,6 +21,7 @@ import java.util.UUID;
import java.util.function.BiConsumer;
@RestController
@Profile("!only-office")
public class HsBookingProjectController implements HsBookingProjectsApi {
@Autowired
@@ -1,12 +1,14 @@
package net.hostsharing.hsadminng.hs.booking.project;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsBookingProjectRbacRepository extends HsBookingProjectRepository<HsBookingProjectRbacEntity>,
Repository<HsBookingProjectRbacEntity, UUID> {
@@ -1,12 +1,14 @@
package net.hostsharing.hsadminng.hs.booking.project;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsBookingProjectRealRepository extends HsBookingProjectRepository<HsBookingProjectRealEntity>,
Repository<HsBookingProjectRealEntity, UUID> {
@@ -1,11 +1,13 @@
package net.hostsharing.hsadminng.hs.booking.project;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsBookingProjectRepository<E extends HsBookingProject> {
@Timed("app.booking.projects.repo.findByUuid")
@@ -15,6 +15,7 @@ import net.hostsharing.hsadminng.mapper.KeyValueMap;
import net.hostsharing.hsadminng.mapper.StrictMapper;
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
@@ -27,6 +28,7 @@ import java.util.UUID;
import java.util.function.BiConsumer;
@RestController
@Profile("!only-office")
public class HsHostingAssetController implements HsHostingAssetsApi {
@Autowired
@@ -4,6 +4,7 @@ import io.micrometer.core.annotation.Timed;
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HostingAssetEntityValidatorRegistry;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetPropsApi;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
@@ -12,6 +13,7 @@ import java.util.Map;
@RestController
@Profile("!only-office")
public class HsHostingAssetPropsController implements HsHostingAssetPropsApi {
@Override
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@@ -8,7 +9,7 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsHostingAssetRbacRepository extends HsHostingAssetRepository<HsHostingAssetRbacEntity>, Repository<HsHostingAssetRbacEntity, UUID> {
@Timed("app.hostingAsset.repo.findByUuid.rbac")
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@@ -9,6 +10,7 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsHostingAssetRealRepository extends HsHostingAssetRepository<HsHostingAssetRealEntity>, Repository<HsHostingAssetRealEntity, UUID> {
@Timed("app.hostingAsset.repo.findByUuid.real")
@@ -1,11 +1,13 @@
package net.hostsharing.hsadminng.hs.hosting.asset;
import io.micrometer.core.annotation.Timed;
import org.springframework.context.annotation.Profile;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Profile("!only-office")
public interface HsHostingAssetRepository<E extends HsHostingAsset> {
@Timed("app.hosting.assets.repo.findByUuid")
@@ -13,9 +13,11 @@ import net.hostsharing.hsadminng.mapper.StrictMapper;
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile("!only-office")
public class HsBookingItemCreatedListener implements ApplicationListener<BookingItemCreatedAppEvent> {
@Autowired