feat: support session audit log (#16703)

Related to https://github.com/coder/coder/issues/15139

Demo:
<img width="1213" alt="Screenshot 2025-02-25 at 16 27 12"
src="https://github.com/user-attachments/assets/9995a68d-5cd4-4b95-9523-dfd5bf4ff48d"
/>

---------

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
This commit is contained in:
Bruno Quaresma
2025-02-26 14:13:11 -03:00
committed by GitHub
co-authored by Mathias Fredriksson
parent 2971957b88
commit f1b357d6f2
3 changed files with 85 additions and 12 deletions
@@ -11,12 +11,15 @@ interface AuditLogDescriptionProps {
export const AuditLogDescription: FC<AuditLogDescriptionProps> = ({
auditLog,
}) => {
let target = auditLog.resource_target.trim();
let user = auditLog.user?.username.trim();
if (auditLog.resource_type === "workspace_build") {
return <BuildAuditDescription auditLog={auditLog} />;
}
if (auditLog.additional_fields?.connection_type) {
return <AppSessionAuditLogDescription auditLog={auditLog} />;
}
let target = auditLog.resource_target.trim();
let user = auditLog.user?.username.trim();
// SSH key entries have no links
if (auditLog.resource_type === "git_ssh_key") {
@@ -57,3 +60,19 @@ export const AuditLogDescription: FC<AuditLogDescriptionProps> = ({
</span>
);
};
function AppSessionAuditLogDescription({ auditLog }: AuditLogDescriptionProps) {
const { connection_type, workspace_owner, workspace_name } =
auditLog.additional_fields;
return (
<>
{connection_type} session to {workspace_owner}'s{" "}
<Link component={RouterLink} to={`${auditLog.resource_link}`}>
<strong>{workspace_name}</strong>
</Link>{" "}
workspace{" "}
<strong>{auditLog.action === "disconnect" ? "closed" : "opened"}</strong>
</>
);
}
@@ -159,3 +159,43 @@ export const NoUserAgent: Story = {
},
},
};
export const WithConnectionType: Story = {
args: {
showOrgDetails: true,
auditLog: {
id: "725ea2f2-faae-4bdd-a821-c2384a67d89c",
request_id: "a486c1cb-6acb-41c9-9bce-1f4f24a2e8ff",
time: "2025-02-24T10:20:08.054072Z",
ip: "fd7a:115c:a1e0:4fa5:9ccd:27e4:5d72:c66a",
user_agent: "",
resource_type: "workspace_agent",
resource_id: "813311fb-bad3-4a92-98cd-09ee57e73d6e",
resource_target: "main",
resource_icon: "",
action: "disconnect",
diff: {},
status_code: 255,
additional_fields: {
reason: "process exited with error status: -1",
build_number: "1",
build_reason: "initiator",
workspace_id: "6a7cfb32-d208-47bb-91d0-ec54b69912b6",
workspace_name: "test2",
connection_type: "SSH",
workspace_owner: "admin",
},
description: "{user} disconnected workspace agent {target}",
resource_link: "",
is_deleted: false,
organization_id: "0e6fa63f-b625-4a6f-ab5b-a8217f8c80b3",
organization: {
id: "0e6fa63f-b625-4a6f-ab5b-a8217f8c80b3",
name: "coder",
display_name: "Coder",
icon: "",
},
user: null,
},
},
};
@@ -128,6 +128,8 @@ export const AuditLogRow: FC<AuditLogRowProps> = ({
</Stack>
<Stack direction="row" alignItems="center">
<StatusPill code={auditLog.status_code} />
{/* With multi-org, there is not enough space so show
everything in a tooltip. */}
{showOrgDetails ? (
@@ -169,6 +171,12 @@ export const AuditLogRow: FC<AuditLogRowProps> = ({
</Link>
</div>
)}
{auditLog.additional_fields?.reason && (
<div>
<h4 css={styles.auditLogInfoHeader}>Reason:</h4>
<div>{auditLog.additional_fields?.reason}</div>
</div>
)}
</div>
}
>
@@ -203,13 +211,6 @@ export const AuditLogRow: FC<AuditLogRowProps> = ({
)}
</Stack>
)}
<Pill
css={styles.httpStatusPill}
type={httpStatusColor(auditLog.status_code)}
>
{auditLog.status_code.toString()}
</Pill>
</Stack>
</Stack>
</Stack>
@@ -218,7 +219,7 @@ export const AuditLogRow: FC<AuditLogRowProps> = ({
{shouldDisplayDiff ? (
<div> {<DropdownArrow close={isDiffOpen} />}</div>
) : (
<div css={styles.columnWithoutDiff}></div>
<div css={styles.columnWithoutDiff} />
)}
</Stack>
@@ -232,6 +233,19 @@ export const AuditLogRow: FC<AuditLogRowProps> = ({
);
};
function StatusPill({ code }: { code: number }) {
const isHttp = code >= 100;
return (
<Pill
css={styles.statusCodePill}
type={isHttp ? httpStatusColor(code) : code === 0 ? "success" : "error"}
>
{code.toString()}
</Pill>
);
}
const styles = {
auditLogCell: {
padding: "0 !important",
@@ -287,7 +301,7 @@ const styles = {
width: "100%",
},
httpStatusPill: {
statusCodePill: {
fontSize: 10,
height: 20,
paddingLeft: 10,