Skip to content

Commit

Permalink
Update dependency requirements and add resolution flow
Browse files Browse the repository at this point in the history
  • Loading branch information
byronantak committed Nov 27, 2024
1 parent eb9a490 commit ef05611
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration()
@Configuration
public class HeaderSecurityConfig {

@Value("${l10n.spring.security.header.user.identifyingHeader:}")
Expand All @@ -18,6 +18,28 @@ public class HeaderSecurityConfig {
@Value("${l10n.spring.security.header.service.delimiter:/}")
protected String serviceDelimiter;

@Value("${l10n.spring.security.header.service.pagerduty.enableFailedAuthIncidents:false}")
protected boolean isPagerDutyEnabled;

@Value("${l10n.spring.security.header.service.pagerduty.integration.name:#{null}}")
protected String pagerDutyIntegrationName;

public boolean isPagerDutyEnabled() {
return isPagerDutyEnabled;
}

public void setPagerDutyEnabled(boolean pagerDutyEnabled) {
isPagerDutyEnabled = pagerDutyEnabled;
}

public String getPagerDutyIntegrationName() {
return pagerDutyIntegrationName;
}

public void setPagerDutyIntegrationName(String pagerDutyIntegrationName) {
this.pagerDutyIntegrationName = pagerDutyIntegrationName;
}

public String getUserIdentifyingHeader() {
return userIdentifyingHeader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ AND LOWER(:serviceName) LIKE CONCAT(LOWER(u.username), '%')
AND u.enabled IS TRUE
""")
@EntityGraph(value = "User.legacy", type = EntityGraphType.FETCH)
Optional<List<User>> findServicesByServiceNameAndPrefix(
List<User> findServicesByServiceNameAndPrefix(
@Param("serviceName") String serviceName, @Param("servicePrefix") String servicePrefix);
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ public class UserService {

@Autowired AuditorAwareImpl auditorAwareImpl;

@Autowired MeterRegistry meterRegistry;

@Autowired(required = false)
ServiceDisambiguator serviceDisambiguator;

@Autowired HeaderSecurityConfig headerSecurityConfig;

@Autowired PagerDutyIntegrationService pagerDutyIntegrationService;
@Autowired(required = false)
HeaderSecurityConfig headerSecurityConfig;

@Autowired MeterRegistry meterRegistry;
@Autowired(required = false)
PagerDutyIntegrationService pagerDutyIntegrationService;

/**
* Allow PMs and ADMINs to create / edit users. However, a PM user can not create / edit ADMIN
Expand Down Expand Up @@ -421,64 +423,114 @@ public User getServiceAccountUser(String serviceName) {
return userRepository.findByUsername(serviceName);
}

Optional<List<User>> users =
if (headerSecurityConfig == null) {
logger.debug("Header config does not exist. Falling back to regular exact match logic");
return userRepository.findByUsername(serviceName);
}

List<User> users =
userRepository.findServicesByServiceNameAndPrefix(
serviceName, headerSecurityConfig.getServicePrefix());
if (users.isEmpty()) {
logger.debug("No matching services found as per DB query");
sendPagerDutyNotification(serviceName);
sendPagerDutyNotification(serviceName, PagerDutyTypeNotificationType.CreateIncident);
logger.error(
"Service '{}' attempted and failed authentication. No matching services found.",
serviceName);
return null;
}

User matchingUser = serviceDisambiguator.getServiceWithCommonAncestor(users.get(), serviceName);
User matchingUser = serviceDisambiguator.getServiceWithCommonAncestor(users, serviceName);
if (matchingUser == null) {
logger.debug("No matching services found as per ServiceDisambiguator");
sendPagerDutyNotification(serviceName);
sendPagerDutyNotification(serviceName, PagerDutyTypeNotificationType.CreateIncident);
logger.error(
"Service '{}' attempted and failed authentication. No services could be fuzzy matched",
serviceName);
throw new UsernameNotFoundException("Service with name '" + serviceName + "' was not found");
} else {
sendPagerDutyNotification(serviceName, PagerDutyTypeNotificationType.ResolveIncident);
}

logger.debug("Matching service found: {}", matchingUser.getUsername());
return matchingUser;
}

private String normalizeServiceName(String serviceName) {
return serviceName
.replaceAll(headerSecurityConfig.getServicePrefix(), "")
.replaceAll(headerSecurityConfig.getServiceDelimiter(), ":");
enum PagerDutyTypeNotificationType {
CreateIncident,
ResolveIncident
}

private void sendPagerDutyNotification(String serviceName) {
Optional<PagerDutyClient> defaultPagerDutyClient =
pagerDutyIntegrationService.getDefaultPagerDutyClient();
if (defaultPagerDutyClient.isEmpty()) {
logger.error("No default Pager Duty client configured");
meterRegistry
.counter(
"UserService.sendPagerDutyNotification.defaultPagerDutyClientNotConfigured",
Tags.of("serviceName", serviceName))
.increment();
private void sendPagerDutyNotification(
String serviceName, PagerDutyTypeNotificationType notificationType) {
if (!headerSecurityConfig.isPagerDutyEnabled()) {
return;
}

PagerDutyClient pagerDutyClient = defaultPagerDutyClient.get();
String dedupKey =
"mojito:auth:unrecognized:service:account:" + normalizeServiceName(serviceName);
if (pagerDutyIntegrationService == null) {
logger.error(
"Pager Duty Integration service is null but configured to send notifications for service auth");
incrementPagerDutyNotConfiguredCounter(serviceName);
return;
}

Optional<PagerDutyClient> configuredPagerDutyClient =
Optional.of(headerSecurityConfig)
.map(HeaderSecurityConfig::getPagerDutyIntegrationName)
.map(
integrationName ->
pagerDutyIntegrationService.getPagerDutyClient((integrationName)))
.orElse(pagerDutyIntegrationService.getDefaultPagerDutyClient());
if (configuredPagerDutyClient.isEmpty()) {
logger.error(
"No PagerDuty client configured with name {}",
Optional.of(headerSecurityConfig.getPagerDutyIntegrationName())
.map(name -> "'" + name + "'")
.orElse("null"));
incrementPagerDutyNotConfiguredCounter(serviceName);
return;
}

PagerDutyClient pagerDutyClient = configuredPagerDutyClient.get();
String dedupKey = buildUnrecognizedServiceDedupKey(serviceName);
try {
pagerDutyClient.triggerIncident(
dedupKey,
new PagerDutyPayload(
"Mojito unrecognized service attempting authentication: '" + serviceName + "'",
serviceName,
PagerDutyPayload.Severity.ERROR,
ImmutableMap.of("serviceName", serviceName)));
if (notificationType == PagerDutyTypeNotificationType.CreateIncident) {
pagerDutyClient.triggerIncident(
dedupKey,
new PagerDutyPayload(
"Mojito unrecognized service attempting authentication: '" + serviceName + "'",
serviceName,
PagerDutyPayload.Severity.ERROR,
ImmutableMap.of("serviceName", serviceName)));
}

if (notificationType == PagerDutyTypeNotificationType.ResolveIncident) {
pagerDutyClient.resolveIncident(dedupKey);
}
} catch (PagerDutyException e) {
logger.error("Unable to trigger pager duty incident for unrecognized service auth", e);
}
}

private String buildUnrecognizedServiceDedupKey(String serviceName) {
String normalizedServiceName =
serviceName
.replaceAll(headerSecurityConfig.getServicePrefix(), "")
.replaceAll(headerSecurityConfig.getServiceDelimiter(), ":");
return "mojito:auth:unrecognized:service:account:" + normalizedServiceName;
}

private void incrementPagerDutyNotConfiguredCounter(String serviceName) {
meterRegistry
.counter(
"UserService.sendPagerDutyNotification.pagerDutyClientNotConfigured",
Tags.of(
"serviceName",
serviceName,
"clientIntegrationName",
Optional.of(headerSecurityConfig)
.map(HeaderSecurityConfig::getPagerDutyIntegrationName)
.orElse("null")))
.increment();
}
}

0 comments on commit ef05611

Please sign in to comment.