33import java .io .IOException ;
44import java .io .InputStream ;
55import java .io .OutputStream ;
6+ import java .nio .charset .StandardCharsets ;
67import java .util .Base64 ;
8+ import io .sentrius .sso .automation .auditing .BaseAccessTokenAuditor ;
9+ import io .sentrius .sso .automation .auditing .Trigger ;
710import io .sentrius .sso .core .integrations .ssh .DataSession ;
811import io .sentrius .sso .core .model .ConnectedSystem ;
12+ import io .sentrius .sso .core .services .SshListenerService ;
913import io .sentrius .sso .protobuf .Session ;
1014import lombok .extern .slf4j .Slf4j ;
1115import org .springframework .web .socket .TextMessage ;
@@ -17,13 +21,24 @@ public class ResponseServiceSession implements DataSession {
1721 private final String sessionId ;
1822 private final InputStream in ;
1923 private final OutputStream out ;
24+ private final BaseAccessTokenAuditor auditor ;
2025 private ConnectedSystem connectedSystem ;
2126
22- public ResponseServiceSession (ConnectedSystem connectedSystem , InputStream in , OutputStream out ) {
27+
28+ private static final String ANSI_RED = "\u001B [31m" ;
29+ private static final String ANSI_YELLOW = "\u001B [33m" ;
30+ private static final String ANSI_GREEN = "\u001B [32m" ;
31+ private static final String ANSI_BLUE = "\u001B [34m" ;
32+ private static final String ANSI_RESET = "\u001B [0m" ;
33+ private static final String ANSI_BOLD = "\u001B [1m" ;
34+
35+ public ResponseServiceSession (ConnectedSystem connectedSystem , InputStream in ,
36+ OutputStream out ) {
2337 this .sessionId = connectedSystem .getWebsocketSessionId ();
2438 this .connectedSystem = connectedSystem ;
2539 this .in = in ;
2640 this .out = out ;
41+ this .auditor = connectedSystem .getTerminalAuditor ();
2742 }
2843 @ Override
2944 public String getId () {
@@ -45,11 +60,142 @@ public void sendMessage(WebSocketMessage<?> message) throws IOException {
4560 Session .TerminalMessage auditLog =
4661 Session .TerminalMessage .parseFrom (messageBytes );
4762
48- log .info ("Sending terminal message to session {}: {} {}" , sessionId , terminalMessage ,
49- auditLog .getCommand ());
50- out .write (auditLog .getCommandBytes ().toByteArray ());
63+ var trigger = auditLog .getTrigger ();
64+ String msg = "" ;
65+ switch (trigger .getAction ()) {
66+ case DENY_ACTION :
67+ msg = formatDenyMessage (trigger , auditLog );
68+ connectedSystem .getCommander ().write (SshListenerService .keyMap .get (3 ));
69+ connectedSystem .getTerminalAuditor ().clear (0 ); // clear in case
70+ break ;
71+ case WARN_ACTION :
72+ msg = formatWarnMessage (trigger , auditLog );
73+
74+ break ;
75+ case PROMPT_ACTION :
76+ msg = formatPromptMessage (trigger , auditLog );
77+ break ;
78+ case JIT_ACTION :
79+ msg = formatJitMessage (trigger , auditLog );
80+ break ;
81+ case RECORD_ACTION :
82+ msg = formatRecordMessage (trigger , auditLog );
83+ break ;
84+
85+ case PERSISTENT_MESSAGE :
86+ msg = formatPersistentMessage (trigger , auditLog );
87+ break ;
88+ case APPROVE_ACTION :
89+ msg = formatApproveMessage (trigger , auditLog );
90+ break ;
91+ case LOG_ACTION :
92+ return ; // Log actions don't show user messages
93+ case ALERT_ACTION :
94+ msg = formatAlertMessage (trigger , auditLog );
95+ break ;
96+ default : {
97+ msg = auditLog .getCommand ();
98+ break ;
99+ }
100+ };
101+
102+ log .info ("Sending terminal message to session {}: " ,
103+ msg );
104+ out .write (msg .getBytes (StandardCharsets .UTF_8 ));
51105 out .flush ();
52106
107+
108+
53109 }
54110 }
111+
112+
113+ private String formatDenyMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
114+ StringBuilder sb = new StringBuilder ();
115+ sb .append ("\r \n " );
116+ sb .append (ANSI_RED ).append (ANSI_BOLD ).append ("⚠ COMMAND BLOCKED ⚠" ).append (ANSI_RESET ).append ("\r \n " );
117+ sb .append (ANSI_RED ).append ("Reason: " ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
118+ sb .append (ANSI_RED ).append ("This command has been blocked by security policy." ).append (ANSI_RESET ).append ("\r \n " );
119+ sb .append ("\r \n " );
120+ return sb .toString ();
121+ }
122+
123+ private String formatWarnMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
124+ StringBuilder sb = new StringBuilder ();
125+ sb .append ("\r \n " );
126+ sb .append (ANSI_YELLOW ).append (ANSI_BOLD ).append ("⚠ WARNING ⚠" ).append (ANSI_RESET ).append ("\r \n " );
127+ sb .append (ANSI_YELLOW ).append ("Warning: " ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
128+ sb .append ("\r \n " );
129+ return sb .toString ();
130+ }
131+
132+ private String formatPromptMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
133+ StringBuilder sb = new StringBuilder ();
134+ sb .append ("\r \n " );
135+ sb .append (ANSI_BLUE ).append (ANSI_BOLD ).append ("📝 PROMPT" ).append (ANSI_RESET ).append ("\r \n " );
136+ sb .append (ANSI_BLUE ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
137+ if (!auditLog .getCommand ().isEmpty ()) {
138+ sb .append (ANSI_BLUE ).append (auditLog .getCommand ()).append (" (y/n): " ).append (ANSI_RESET );
139+ }
140+ return sb .toString ();
141+ }
142+
143+ private String formatJitMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
144+ StringBuilder sb = new StringBuilder ();
145+ sb .append ("\r \n " );
146+ sb .append (ANSI_YELLOW ).append (ANSI_BOLD ).append ("🔐 JUST-IN-TIME ACCESS" ).append (ANSI_RESET ).append ("\r \n " );
147+ sb .append (ANSI_YELLOW ).append ("Reason: " ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
148+ sb .append (ANSI_YELLOW ).append ("Requesting access..." ).append (ANSI_RESET ).append ("\r \n " );
149+ sb .append ("\r \n " );
150+ return sb .toString ();
151+ }
152+
153+ private String formatRecordMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
154+ StringBuilder sb = new StringBuilder ();
155+ sb .append ("\r \n " );
156+ sb .append (ANSI_GREEN ).append (ANSI_BOLD ).append ("📹 RECORDING" ).append (ANSI_RESET ).append ("\r \n " );
157+ sb .append (ANSI_GREEN ).append ("This session is being recorded for audit purposes." ).append (ANSI_RESET ).append ("\r \n " );
158+ if (!trigger .getDescription ().isEmpty ()) {
159+ sb .append (ANSI_GREEN ).append ("Reason: " ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
160+ }
161+ sb .append ("\r \n " );
162+ return sb .toString ();
163+ }
164+
165+ private String formatPersistentMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
166+ StringBuilder sb = new StringBuilder ();
167+ sb .append ("\r \n " );
168+ sb .append (ANSI_BLUE ).append (ANSI_BOLD ).append ("💬 MESSAGE" ).append (ANSI_RESET ).append ("\r \n " );
169+ sb .append (ANSI_BLUE ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
170+ sb .append ("\r \n " );
171+ return sb .toString ();
172+ }
173+
174+ private String formatApproveMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
175+ StringBuilder sb = new StringBuilder ();
176+ sb .append ("\r \n " );
177+ sb .append (ANSI_GREEN ).append (ANSI_BOLD ).append ("✅ APPROVED" ).append (ANSI_RESET ).append ("\r \n " );
178+ sb .append (ANSI_GREEN ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
179+ sb .append ("\r \n " );
180+ return sb .toString ();
181+ }
182+
183+ private String formatAlertMessage (Session .Trigger trigger , Session .TerminalMessage auditLog ) {
184+ StringBuilder sb = new StringBuilder ();
185+ sb .append ("\r \n " );
186+ sb .append (ANSI_RED ).append (ANSI_BOLD ).append ("🚨 ALERT" ).append (ANSI_RESET ).append ("\r \n " );
187+ sb .append (ANSI_RED ).append (trigger .getDescription ()).append (ANSI_RESET ).append ("\r \n " );
188+ sb .append ("\r \n " );
189+ return sb .toString ();
190+ }
191+
192+ /**
193+ * Sends a plain message to the terminal
194+ */
195+ public void sendMessage (String message , OutputStream out ) throws IOException {
196+ if (message != null && !message .isEmpty ()) {
197+ out .write (message .getBytes ());
198+ out .flush ();
199+ }
200+ }
55201}
0 commit comments