Skip to content

Commit

Permalink
Parsed body for entries of type HashedRekord (including x509 parsing) (
Browse files Browse the repository at this point in the history
  • Loading branch information
pdeslaur authored May 24, 2022
1 parent 9fd20b9 commit fe85051
Show file tree
Hide file tree
Showing 8 changed files with 537 additions and 198 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,26 @@
"@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.4.4",
"@mui/material": "^5.5.0",
"@peculiar/x509": "^1.6.1",
"@peculiar/x509": "^1.6.4",
"@react-rxjs/core": "0.9.6",
"@react-rxjs/utils": "0.9.5",
"@types/js-yaml": "^4.0.5",
"@types/react-highlight": "^0.12.5",
"js-yaml": "^4.1.0",
"moment": "^2.29.3",
"next": "^12.1.6",
"react": "^18.0.0-rc.1",
"react-dom": "^18.0.0-rc.1",
"react-error-boundary": "^3.1.4",
"react-highlight": "^0.14.0",
"react-hook-form": "^7.31.0",
"react-syntax-highlighter": "^15.5.0",
"rxjs": "^7.5.4",
"sass": "^1.49.9",
"sharp": "^0.30.2"
},
"devDependencies": {
"@types/node": "17.0.21",
"@types/react": "18.0.9",
"@types/react-syntax-highlighter": "^15.5.1",
"eslint": "8.10.0",
"eslint-config-next": "12.1.0",
"openapi-typescript-codegen": "^0.22.0",
Expand Down
128 changes: 79 additions & 49 deletions src/modules/components/Entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import {
} from "@mui/material";
import { Box } from "@mui/system";
import { dump, load } from "js-yaml";
import moment from "moment";
import { Convert } from "pvtsutils";
import { ReactNode } from "react";
import Highlight from "react-highlight";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { atomDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { LogEntry } from "../api/generated";
import { HashedRekord } from "../api/generated/types/hashedrekord";
import { toRelativeDateString } from "../utils/date";
import { HashedRekordViewer } from "./HashedRekord";

const DUMP_OPTIONS: jsyaml.DumpOptions = {
replacer: (key, value) => {
Expand All @@ -31,6 +34,25 @@ const DUMP_OPTIONS: jsyaml.DumpOptions = {
},
};

const AccordionDetails = styled(MuiAccordionDetails)({
padding: 0,
});

/**
* Return a parsed JSON object of the provided content.
* If an error occurs, the provided content is returned as a raw string.
*/
function tryJSONParse(content?: string): unknown {
if (!content) {
return content;
}
try {
return JSON.parse(content);
} catch (e) {
return content;
}
}

export function Card({
title,
content,
Expand Down Expand Up @@ -79,45 +101,13 @@ export function Card({
);
}

const SecondarySpan = styled("span")(({ theme }) => ({
color: theme.palette.info.main,
paddingInlineStart: theme.spacing(1),
}));

const AccordionDetails = styled(MuiAccordionDetails)({
padding: 0,
});

function RelativeDate({ date }: { date: Date }) {
return (
<>
{moment().to(date)}
<SecondarySpan>({moment(date).format()})</SecondarySpan>
</>
);
}

/**
* Return a parsed JSON object of the provided content.
* If an error occurs, the provided content is returned as a raw string.
*/
function tryJSONParse(content?: string): unknown {
if (!content) {
return content;
}
try {
return JSON.parse(content);
} catch (e) {
return content;
}
}

export function Entry({ entry }: { entry: LogEntry }) {
const [uuid, obj] = Object.entries(entry)[0];

const body = JSON.parse(window.atob(obj.body)) as {
kind: string;
spec: string;
apiVersion: string;
spec: unknown;
};

// Extract the JSON payload of the attestation. Some attestations appear to be
Expand All @@ -129,8 +119,18 @@ export function Entry({ entry }: { entry: LogEntry }) {
}
const attestation = tryJSONParse(rawAttestation);

let parsed: ReactNode | undefined;
switch (body.kind) {
case "hashedrekord":
parsed = <HashedRekordViewer hashedRekord={body.spec as HashedRekord} />;
break;
}

return (
<Paper sx={{ mb: 2, p: 1 }}>
<Paper
sx={{ mb: 2, p: 1 }}
elevation={4}
>
<Typography
variant="h5"
component="h2"
Expand Down Expand Up @@ -180,11 +180,7 @@ export function Entry({ entry }: { entry: LogEntry }) {
>
<Card
title="Integrated time"
content={
<span>
<RelativeDate date={new Date(obj.integratedTime * 1000)} />
</span>
}
content={toRelativeDateString(new Date(obj.integratedTime * 1000))}
dividerSx={{
display: {
xs: "none",
Expand All @@ -194,34 +190,68 @@ export function Entry({ entry }: { entry: LogEntry }) {
/>
</Grid>
</Grid>
<Highlight className="yaml">{dump(body.spec, DUMP_OPTIONS)}</Highlight>
<Divider
flexItem
sx={{ my: 1 }}
/>
{parsed}
<Box sx={{ mt: 1 }}>
<>
<Accordion
disableGutters
defaultExpanded={!parsed}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="body-content"
id="body-header"
>
<Typography>Raw Body</Typography>
</AccordionSummary>
<AccordionDetails>
<SyntaxHighlighter
language="yaml"
style={atomDark}
>
{dump(body, DUMP_OPTIONS)}
</SyntaxHighlighter>
</AccordionDetails>
</Accordion>
{attestation && (
<Accordion disableGutters>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2a-content"
id="panel2a-header"
aria-controls="attestation-content"
id="attestation-header"
>
<Typography>Attestation</Typography>
</AccordionSummary>
<AccordionDetails>
<Highlight className="yaml">{dump(attestation)}</Highlight>
<SyntaxHighlighter
language="yaml"
style={atomDark}
>
{dump(attestation)}
</SyntaxHighlighter>
</AccordionDetails>
</Accordion>
)}
{obj.verification && (
<Accordion disableGutters>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2a-content"
id="panel2a-header"
aria-controls="verification-content"
id="verification-header"
>
<Typography>Verification</Typography>
</AccordionSummary>
<AccordionDetails>
<Highlight className="yaml">{dump(obj.verification)}</Highlight>
<SyntaxHighlighter
language="yaml"
style={atomDark}
>
{dump(obj.verification)}
</SyntaxHighlighter>
</AccordionDetails>
</Accordion>
)}
Expand Down
57 changes: 57 additions & 0 deletions src/modules/components/HashedRekord.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Box, Typography } from "@mui/material";
import { dump } from "js-yaml";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { atomDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { HashedRekord } from "../api/generated/types/hashedrekord";
import { decodex509 } from "../x509/decode";

export function HashedRekordViewer({
hashedRekord,
}: {
hashedRekord: HashedRekord;
}) {
const certContent = window.atob(
hashedRekord.signature.publicKey?.content || ""
);

return (
<Box>
<Typography
variant="h5"
sx={{ py: 1 }}
>
Hash
</Typography>
<SyntaxHighlighter
language="text"
style={atomDark}
>
{`${hashedRekord.data.hash?.algorithm}:${hashedRekord.data.hash?.value}`}
</SyntaxHighlighter>
<Typography
variant="h5"
sx={{ py: 1 }}
>
Signature
</Typography>
<SyntaxHighlighter
language="text"
style={atomDark}
>
{hashedRekord.signature.content || ""}
</SyntaxHighlighter>
<Typography
variant="h5"
sx={{ py: 1 }}
>
Certificate
</Typography>
<SyntaxHighlighter
language="yaml"
style={atomDark}
>
{dump(decodex509(certContent))}
</SyntaxHighlighter>
</Box>
);
}
5 changes: 5 additions & 0 deletions src/modules/utils/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import moment from "moment";

export function toRelativeDateString(date: Date) {
return `${moment().to(date)} (${moment(date).format()})`;
}
Loading

1 comment on commit fe85051

@vercel
Copy link

@vercel vercel bot commented on fe85051 May 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

rekor-search-ui – ./

rekor-search-ui.vercel.app
rekor.tlog.dev
rekor-search-ui-git-main.chainguard.app
rekor-search-ui.chainguard.app

Please sign in to comment.