Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gcp.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SENTRIUS_VERSION=1.0.18
SENTRIUS_VERSION=1.0.23
SENTRIUS_SSH_VERSION=1.0.2
SENTRIUS_KEYCLOAK_VERSION=1.0.4
SENTRIUS_AGENT_VERSION=1.0.13
SENTRIUS_AGENT_VERSION=1.0.14
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ WORKDIR /app
# Copy the pre-built API JAR into the container
COPY api/target/sentrius-api-1.0.0-SNAPSHOT.jar /app/sentrius.jar
COPY docker/sentrius/exampleInstallWithTypes.yml /app/exampleInstallWithTypes.yml
COPY docker/sentrius/demoInstaller.yml /app/demoInstaller.yml

# Expose the port the app runs on
EXPOSE 8080
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,37 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.sentrius.sso.core.model.metadata.AnalyticsTracking;
import io.sentrius.sso.core.model.metadata.TerminalBehaviorMetrics;
import io.sentrius.sso.core.model.metadata.TerminalCommand;
import io.sentrius.sso.core.model.metadata.TerminalRiskIndicator;
import io.sentrius.sso.core.model.metadata.TerminalSessionMetadata;
import io.sentrius.sso.core.model.metadata.UserExperienceMetrics;
import io.sentrius.sso.core.model.security.IntegrationSecurityToken;
import io.sentrius.sso.core.model.sessions.TerminalLogs;
import io.sentrius.sso.core.repository.AnalyticsTrackingRepository;
import io.sentrius.sso.core.services.IntegrationSecurityTokenService;
import io.sentrius.sso.core.services.PluggableServices;
import io.sentrius.sso.core.services.SessionService;
import io.sentrius.sso.core.services.metadata.TerminalBehaviorMetricsService;
import io.sentrius.sso.core.services.metadata.TerminalCommandService;
import io.sentrius.sso.core.services.metadata.TerminalRiskIndicatorService;
import io.sentrius.sso.core.services.metadata.TerminalSessionMetadataService;
import io.sentrius.sso.core.services.metadata.UserExperienceMetricsService;
import io.sentrius.sso.core.utils.JsonUtil;
import io.sentrius.sso.integrations.external.ExternalIntegrationDTO;
import io.sentrius.sso.security.ApiKey;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

Expand All @@ -42,6 +51,8 @@ public class SessionAnalyticsAgent {
private final UserExperienceMetricsService experienceMetricsService;
private final AnalyticsTrackingRepository trackingRepository;
private final SessionService sessionService;
final IntegrationSecurityTokenService integrationSecurityTokenService;


@Scheduled(fixedDelay = 60000) // Waits 60 seconds after the previous run completes
@Transactional
Expand All @@ -66,7 +77,35 @@ public void processSessions() {
// session.setSessionStatus("PROCESSED");
// sessionMetadataService.saveSession(session);
}

log.info("Finished processing sessions");
}
/* TODO - Implement this
@Scheduled(fixedDelay = 60000) // Waits 60 seconds after the previous run completes
@Transactional
public void processTerminalCommands() {
log.info("Processing terminal commands...");

var openaiService = integrationSecurityTokenService.findByConnectionType("openai").stream().findFirst().orElse(null);

if (null != openaiService){
log.info("OpenAI service is available");
ExternalIntegrationDTO externalIntegrationDTO = null;
try {
externalIntegrationDTO = JsonUtil.MAPPER.readValue(openAiToken.getConnectionInfo(),
ExternalIntegrationDTO.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
ApiKey key =
ApiKey.builder().apiKey(externalIntegrationDTO.getApiToken()).principal(externalIntegrationDTO.getUsername()).build();

} else {
log.info("OpenAI service is not enabled");
}

log.info("Finished processing terminal commands");
}*/

private void processSession(TerminalSessionMetadata session) {

Expand Down
2 changes: 1 addition & 1 deletion api/dynamic.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ enableInternalAudit=true
twopartyapproval.require.explanation.LOCKING_SYSTEMS=false
canApproveOwnJITs=false
allowUploadSystemConfiguration = true
yamlConfigurationPath=/mnt/ExtraDrive/repos/Sentrius/docker/sentrius/exampleInstallWithTypes.yml
yamlConfigurationPath=/mnt/ExtraDrive/repos/Sentrius/docker/sentrius/demoInstaller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import com.jcraft.jsch.JSchException;
import io.sentrius.sso.automation.auditing.RuleFactory;
import io.sentrius.sso.automation.sideeffects.SideEffect;
import io.sentrius.sso.automation.sideeffects.SideEffectType;
import io.sentrius.sso.core.config.SystemOptions;
Expand All @@ -28,6 +29,7 @@
import io.sentrius.sso.core.model.dto.HostSystemDTO;
import io.sentrius.sso.core.model.dto.UserTypeDTO;
import io.sentrius.sso.core.model.hostgroup.HostGroup;
import io.sentrius.sso.core.model.hostgroup.ProfileRule;
import io.sentrius.sso.core.model.security.UserType;
import io.sentrius.sso.core.model.security.enums.ApplicationAccessEnum;
import io.sentrius.sso.core.model.security.enums.AutomationAccessEnum;
Expand All @@ -43,9 +45,12 @@
import io.sentrius.sso.core.repository.UserTypeRepository;
import io.sentrius.sso.core.security.service.CryptoService;
import io.sentrius.sso.core.services.HostGroupService;
import io.sentrius.sso.core.services.RuleService;
import io.sentrius.sso.core.services.UserService;
import io.sentrius.sso.install.configuration.InstallConfiguration;
import io.sentrius.sso.install.configuration.dtos.HostGroupConfigurationDTO;
import io.sentrius.sso.install.configuration.dtos.RuleDTO;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
Expand All @@ -70,12 +75,15 @@ public class ConfigurationApplicationTask {

final UserTypeRepository userTypeRepository;

final RuleService ruleService;

final UserService userService;
private final HostGroupService hostGroupService;

final CryptoService cryptoService;

@EventListener(ApplicationReadyEvent.class)
@Transactional
public void afterStartup() throws IOException, GeneralSecurityException, JSchException, SQLException {
// Your logic here

Expand Down Expand Up @@ -131,7 +139,7 @@ public void afterStartup() throws IOException, GeneralSecurityException, JSchExc
log.info("No configuration file found");
}
}

@Transactional
public List<SideEffect> createStaticType(UserType type, boolean action) throws SQLException,
GeneralSecurityException {

Expand Down Expand Up @@ -160,7 +168,7 @@ public List<SideEffect> createStaticType(UserType type, boolean action) throws S
return sideEffects;
}


@Transactional
public List<SideEffect> initialize(InstallConfiguration installConfiguration, boolean action)
throws SQLException,
GeneralSecurityException,
Expand Down Expand Up @@ -188,19 +196,38 @@ public List<SideEffect> initialize(InstallConfiguration installConfiguration, bo

// create profiles and assign systems

var profiles = createHostGroups(sideEffects, installConfiguration, action);
var rules = createRules(sideEffects, installConfiguration, action);

var profiles = createHostGroups(sideEffects, rules, installConfiguration, action);

createUsers(sideEffects, installConfiguration, userTypes, profiles, action);




// create automation assignments

//AppConfig.encryptProperty("initialized", Instant.now().toString());

return sideEffects;
}
@Transactional
protected Map<String,ProfileRule> createRules(
List<SideEffect> sideEffects, InstallConfiguration installConfiguration,
boolean action
) {
Map<String,ProfileRule> rules = new HashMap<>();
var configuredRules = installConfiguration.getRules();
for(RuleDTO rule : configuredRules) {
ProfileRule newRule =
ProfileRule.builder().ruleClass(rule.getRuleClass()).ruleName(rule.getDisplayName()).ruleConfig(rule.getConfiguration()).build();
newRule = ruleService.saveRule(newRule);
rules.put(rule.getDisplayName(), newRule);
}
return rules;
}


private List<HostGroup> createHostGroups(List<SideEffect> sideEffects, InstallConfiguration installConfiguration,
@Transactional
protected List<HostGroup> createHostGroups(List<SideEffect> sideEffects, Map<String,ProfileRule> rules, InstallConfiguration installConfiguration,
boolean action)
throws JSchException, GeneralSecurityException, IOException {
List<HostGroup> profiles = new ArrayList<>();
Expand Down Expand Up @@ -235,12 +262,21 @@ private List<HostGroup> createHostGroups(List<SideEffect> sideEffects, InstallCo
if (!systems.isEmpty()) {
hostGroup.setHostSystems(systems);
}

for( var assignedRule : hostGroupDto.getAssignedRules() ) {
if (rules.containsKey(assignedRule)) {
var rule = rules.get(assignedRule);
hostGroup.getRules().add(rule);
rule.getHostGroups().add(hostGroup);
}
};
}
var hostGroups = hostGroupService.getHostGroupsByName(hostGroup.getName());
if (hostGroups.isEmpty()) {
if (action) {

hostGroup = hostGroupRepository.save(hostGroup);
log.info("Creating Host Group {} with {}", hostGroup.getId(), hostGroupDto.getDisplayName());
profiles.add(hostGroup);
for(var hs : hostGroup.getHostSystems()) {
if (null == hs.getHostGroups()){
Expand Down Expand Up @@ -284,7 +320,8 @@ private List<HostGroup> createHostGroups(List<SideEffect> sideEffects, InstallCo
return profiles;
}

private List<SideEffect> createSystems(InstallConfiguration installConfiguration, boolean action) throws SQLException,
@Transactional
protected List<SideEffect> createSystems(InstallConfiguration installConfiguration, boolean action) throws SQLException,
GeneralSecurityException {
List<SideEffect> sideEffects = new ArrayList<>();
if (null != installConfiguration.getSystems()) {
Expand All @@ -303,7 +340,8 @@ private List<SideEffect> createSystems(InstallConfiguration installConfiguration
return sideEffects;
}

private boolean shouldInsertSystem(HostSystem systemObj) {
@Transactional
protected boolean shouldInsertSystem(HostSystem systemObj) {
var systems = systemRepository.findByDisplayName(systemObj.getDisplayName());
if (systems.isEmpty()) {
return true;
Expand All @@ -316,6 +354,7 @@ private boolean shouldInsertSystem(HostSystem systemObj) {
return true;
}

@Transactional
protected List<UserType> createUserTypes(List<SideEffect> sideEffects, InstallConfiguration installConfiguration,
boolean action) throws SQLException, GeneralSecurityException {
List<UserType> types = new ArrayList<>();
Expand Down Expand Up @@ -365,6 +404,7 @@ protected List<UserType> createUserTypes(List<SideEffect> sideEffects, InstallCo
return types;
}

@Transactional
protected List<User> createUsers(
List<SideEffect> sideEffects, InstallConfiguration installConfiguration, List<UserType> userTypes,
List<HostGroup> profiles, boolean action)
Expand Down Expand Up @@ -466,6 +506,8 @@ static void createOrUpdate(Map<Long, Set<Long>> assignments, Long profileId, Lon
set.add(userId);
}


@Transactional
protected List<SideEffect> createAdminUser(InstallConfiguration installConfiguration, boolean action) throws NoSuchAlgorithmException {

var user = installConfiguration.getAdminUser();
Expand Down Expand Up @@ -501,6 +543,7 @@ protected List<SideEffect> createAdminUser(InstallConfiguration installConfigura
return sideEffects;
}

@Transactional
protected void createSystemUser(InstallConfiguration connection) throws NoSuchAlgorithmException {

User user = User.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.sentrius.sso.core.model.auditing.Rule;
import io.sentrius.sso.core.services.PluggableServices;
import io.sentrius.sso.core.services.terminal.SessionTrackingService;
import io.sentrius.sso.install.configuration.dtos.RuleDTO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
Expand Down Expand Up @@ -41,4 +42,5 @@ public static void createRules(
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,33 @@
import java.util.Optional;
import io.sentrius.sso.automation.auditing.Trigger;
import io.sentrius.sso.automation.auditing.TriggerAction;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.regex.Pattern;

@Slf4j
public class SudoPrevention extends CommandEvaluator {

// Updated pattern to match both 'sudo' and 'su' as standalone commands (case-insensitive)
private static final Pattern SUDO_SU_PATTERN = Pattern.compile("\\b(sudo|su)\\b", Pattern.CASE_INSENSITIVE);

public SudoPrevention() {
action = TriggerAction.DENY_ACTION;
isSanitized = true;
}

@Override
public Optional<Trigger> trigger(String text) {
if (text.contains("sudo") || text.contains("SUDO")) {
return Optional.of(new Trigger(action, "SUDO is not allowed"));
if (text == null || text.isEmpty()) {
return Optional.empty();
}

// Check if the input contains 'sudo' or 'su'
if (SUDO_SU_PATTERN.matcher(text).find()) {
// Log the blocked attempt
log.info("Blocked SUDO/SU attempt: {}", text);
return Optional.of(new Trigger(action, "SUDO and SU are not allowed"));
}

return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonManagedReference;
Expand Down Expand Up @@ -89,9 +90,10 @@ public class HostGroup {
joinColumns = @JoinColumn(name = "system_id"),
inverseJoinColumns = @JoinColumn(name = "rule_id")
)
private Set<ProfileRule> rules;
@Builder.Default
private Set<ProfileRule> rules = new HashSet<>();

@OneToOne(cascade = CascadeType.ALL)
@OneToOne(cascade = {CascadeType.MERGE, CascadeType.REMOVE})
@JoinColumn(name = "application_key_id", referencedColumnName = "id", unique = true)
private ApplicationKey applicationKey;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.sentrius.sso.core.model.hostgroup;

import java.util.HashSet;
import java.util.Set;
import io.sentrius.sso.core.model.auditing.Rule;
import jakarta.persistence.Column;
Expand All @@ -11,6 +12,7 @@
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand Down Expand Up @@ -41,6 +43,7 @@ public class ProfileRule extends Rule {
private String ruleConfig;

@ManyToMany(mappedBy = "rules", fetch = FetchType.EAGER)
private Set<HostGroup> hostGroups;
@Builder.Default
private Set<HostGroup> hostGroups = new HashSet<>();

}
Loading
Loading