Skip to content

Commit

Permalink
Add certificate chain information to display additional info for cert…
Browse files Browse the repository at this point in the history
…ificate (#491)
  • Loading branch information
AbbyB97 committed Oct 10, 2023
1 parent 1d2fadc commit f9da071
Show file tree
Hide file tree
Showing 331 changed files with 1,194 additions and 843 deletions.
8 changes: 4 additions & 4 deletions cypress/component/FlowChart.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const nodes: CustomNode[] = [
width: 350,
height: 100,
data: {
entityType: "Certificate",
customNodeCardTitle: "Certificate",
entityLabel: "demo.3key.test",
icon: "fa fa-certificate",
isMainNode: true,
Expand Down Expand Up @@ -51,7 +51,7 @@ const nodes: CustomNode[] = [
width: 350,
height: 100,
data: {
entityType: "Certificate Issuer",
customNodeCardTitle: "Certificate Issuer",
icon: "fa fa fa fa-stamp",
entityLabel: "Demo MS Sub CA",
otherProperties: [
Expand All @@ -78,7 +78,7 @@ const nodes: CustomNode[] = [
width: 350,
height: 100,
data: {
entityType: "RA Profile",
customNodeCardTitle: "RA Profile",
icon: "fa fa fa-address-card",
entityLabel: "ms-adcs-webserver",
otherProperties: [
Expand All @@ -101,7 +101,7 @@ const nodes: CustomNode[] = [
width: 350,
height: 100,
data: {
entityType: "Authority",
customNodeCardTitle: "Authority",
icon: "fa fa fa-stamp",
entityLabel: "ms-adcs-lab02-authority",
otherProperties: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function FloatingConnectionLine({ toX, toY, fromPosition, toPosition, fromNode }
width: nodeWidth,
height: nodeHeight,
data: {
entityType: "NA",
customNodeCardTitle: "NA",
entityLabel: "NA",
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
display: flex;
flex-direction: column;
align-items: start;
min-width: 350px;
width: 400px;
min-height: 55px;
border-style: solid;
border-color: #3754a566;
border-width: 2px;
text-align: left;
max-width: 515px;
z-index: 1;
box-shadow: 2.25px 2.25px 0.75px -0.75px rgba(0, 0, 0, 0.15), 1.5px 1.5px 0.75px 0px rgba(0, 0, 0, 0.105),
box-shadow:
2.25px 2.25px 0.75px -0.75px rgba(0, 0, 0, 0.15),
1.5px 1.5px 0.75px 0px rgba(0, 0, 0, 0.105),
0.75px 0.75px 2.25px 0px rgba(0, 0, 0, 0.09);
}

Expand All @@ -42,7 +43,7 @@
background-color: #eee;
}

.entityType {
.customNodeCardTitle {
color: $gray-500;
font-weight: bold;
font-size: medium;
Expand Down Expand Up @@ -77,7 +78,7 @@
}

.listStyle {
max-width: 300px;
max-width: 375px;
}

.propertyName {
Expand All @@ -88,6 +89,7 @@
.propertyValue {
font-weight: 500;
color: $gray-600;
word-wrap: break-word;
}
.mainNodeBody {
border-width: 3px;
Expand Down
12 changes: 10 additions & 2 deletions src/components/FlowChart/CustomFlowNode/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ export default function CustomFlowNode({ data, dragging, selected, xPos, yPos }:
<div className="d-flex my-1">
<i className={cx(style.iconStyle, data.icon, getStatusClasses())}></i>

<h6 className={cx(style.entityType, "my-auto ms-2")}>{data.entityType}</h6>
<h6 className={cx(style.customNodeCardTitle, "my-auto ms-2")}>{data.customNodeCardTitle}</h6>
</div>

{data.redirectUrl ? (
<div className={cx("d-flex ms-2", style.entityLabel)}>
<h6>Entity Name :</h6>
&nbsp;
<Link to={data.redirectUrl}>
<h6>{data.entityLabel}</h6>
<h6 className="text-wrap">{data.entityLabel}</h6>
</Link>
</div>
) : (
Expand All @@ -120,6 +120,14 @@ export default function CustomFlowNode({ data, dragging, selected, xPos, yPos }:
<li key={index} className="list-group-item text-wrap p-0 ">
<span className={style.propertyName}>{property.propertyName} : </span>
<span className={style.propertyValue}>{property.propertyValue}</span>
{property?.copyable && (
<i
onClick={() => {
navigator.clipboard.writeText(property.propertyValue);
}}
className="fa fa-copy ms-2"
></i>
)}
</li>
))}
</ul>
Expand Down
9 changes: 5 additions & 4 deletions src/components/FlowChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface FlowChartProps {
flowChartNodes: CustomNode[];
flowChartEdges: Edge[];
defaultViewport?: Viewport | undefined;
busy?: boolean;
}

const edgeTypes = {
Expand All @@ -42,15 +43,15 @@ const edgeTypes = {
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));

export const nodeWidth = 350;
export const nodeWidth = 400;
export const nodeHeight = 100;

const getLayoutedElements = (nodes: CustomNode[], edges: Edge[], direction = "TB") => {
const isHorizontal = direction === "LR";
dagreGraph.setGraph({ rankdir: direction });

nodes.forEach((node) => {
const currentNodeHeight = node.data.otherProperties?.length ? nodeHeight + node.data.otherProperties?.length * 40 : nodeHeight;
const currentNodeHeight = node.data.otherProperties?.length ? nodeHeight + node.data.otherProperties?.length * 20 : nodeHeight;
dagreGraph.setNode(node.id, { width: nodeWidth, height: currentNodeHeight });
});

Expand All @@ -76,7 +77,7 @@ const getLayoutedElements = (nodes: CustomNode[], edges: Edge[], direction = "TB
return { nodes, edges };
};

const FlowChart = ({ flowChartTitle, flowChartEdges, flowChartNodes, defaultViewport }: FlowChartProps) => {
const FlowChart = ({ flowChartTitle, flowChartEdges, flowChartNodes, defaultViewport, busy }: FlowChartProps) => {
const [nodes, setNodes] = useState(flowChartNodes);
const [edges, setEdges] = useState(flowChartEdges);
const defaultEdgeOptions = { animated: true };
Expand All @@ -93,7 +94,7 @@ const FlowChart = ({ flowChartTitle, flowChartEdges, flowChartNodes, defaultView
}, [flowChartEdges, flowChartNodes]);

return (
<Widget className={style.flowWidget}>
<Widget className={style.flowWidget} busy={busy}>
{flowChartTitle && <h5 className="text-muted">{flowChartTitle}</h5>}
<div className={cx(style.flowChartContainer, style.floatingedges)}>
<ReactFlow
Expand Down
57 changes: 49 additions & 8 deletions src/components/_pages/certificates/detail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ import CertificateRekeyDialog from "../CertificateRekeyDialog";
import CertificateRenewDialog from "../CertificateRenewDialog";

import cx from "classnames";
import FlowChart from "components/FlowChart";
import FlowChart, { CustomNode } from "components/FlowChart";
import { transformCertifacetObjectToNodesAndEdges } from "ducks/transform/certificates";
import { Edge } from "reactflow";
import { LockWidgetNameEnum } from "types/widget-locks";
import { DeviceType, useDeviceType } from "utils/common-hooks";
import CertificateStatus from "../CertificateStatus";
Expand All @@ -72,6 +73,7 @@ export default function CertificateDetail() {
const { id } = useParams();

const certificate = useSelector(selectors.certificateDetail);
const certificateChain = useSelector(selectors.certificateChain);

const groups = useSelector(groupSelectors.certificateGroups);
const raProfiles = useSelector(raProfileSelectors.raProfiles);
Expand All @@ -87,6 +89,10 @@ export default function CertificateDetail() {

const [groupAttributesCallbackAttributes, setGroupAttributesCallbackAttributes] = useState<AttributeDescriptorModel[]>([]);

const [certificateNodes, setCertificateNodes] = useState<CustomNode[]>([]);
const [certificateEdges, setCertificateEdges] = useState<Edge[]>([]);

const [isFlowTabOpenend, setIsFlowTabOpenend] = useState<boolean>(false);
const [groupOptions, setGroupOptions] = useState<{ label: string; value: string }[]>([]);
const [raProfileOptions, setRaProfileOptions] = useState<{ label: string; value: string }[]>([]);
const [userOptions, setUserOptions] = useState<{ label: string; value: string }[]>([]);
Expand All @@ -108,6 +114,7 @@ export default function CertificateDetail() {
const isRenewing = useSelector(selectors.isRenewing);
const isRekeying = useSelector(selectors.isRekeying);
const isFetchingValidationResult = useSelector(selectors.isFetchingValidationResult);
const isFetchingCertificateChain = useSelector(selectors.isFetchingCertificateChain);

const [confirmDelete, setConfirmDelete] = useState<boolean>(false);
const [renew, setRenew] = useState<boolean>(false);
Expand Down Expand Up @@ -150,6 +157,7 @@ export default function CertificateDetail() {
isRevoking ||
isRenewing ||
isRekeying ||
isFetchingCertificateChain ||
isFetchingApprovals,
[
isFetching,
Expand All @@ -160,17 +168,26 @@ export default function CertificateDetail() {
isRevoking,
isRenewing,
isRekeying,
isFetchingCertificateChain,
isFetchingApprovals,
],
);

const { nodes: certificateNodes, edges: certificateEdges } = transformCertifacetObjectToNodesAndEdges(
certificate,
users,
certLocations,
raProfileSelected,
);
const transformCertificate = useCallback(() => {
const { nodes, edges } = transformCertifacetObjectToNodesAndEdges(
certificate,
users,
certLocations,
raProfileSelected,
certificateChain,
);
setCertificateNodes(nodes);
setCertificateEdges(edges);
}, [certificate, users, certLocations, raProfileSelected, certificateChain]);

useEffect(() => {
transformCertificate();
}, [transformCertificate]);
const health = useSelector(utilsActuatorSelectors.health);
const settings = useSelector(settingSelectors.platformSettings);

Expand Down Expand Up @@ -211,6 +228,16 @@ export default function CertificateDetail() {
dispatch(actions.listCertificateApprovals({ uuid: id, paginationRequestDto: {} }));
}, [dispatch, id]);

const getCertificateChainDetails = useCallback(() => {
if (!id) return;
dispatch(actions.getCertificateChain({ uuid: id, withEndCertificate: false }));
}, [dispatch, id]);

useEffect(() => {
if (!id && isFlowTabOpenend) return;
getCertificateChainDetails();
}, [isFlowTabOpenend, id]);

useEffect(() => {
getFreshCertificateLocations();
}, [getFreshCertificateLocations]);
Expand Down Expand Up @@ -1130,7 +1157,16 @@ export default function CertificateDetail() {
},
{
id: "issuerCommonName",
columns: ["Issuer Common Name", certificate.issuerCommonName || ""],
columns: [
"Issuer Common Name",
certificate?.issuerCommonName && certificate?.issuerCertificateUuid ? (
<Link to={`../certificates/detail/${certificate.issuerCertificateUuid}`}>{certificate.issuerCommonName}</Link>
) : certificate?.issuerCommonName ? (
certificate.issuerCommonName
) : (
""
),
],
},
{
id: "issuerDN",
Expand Down Expand Up @@ -1647,8 +1683,13 @@ export default function CertificateDetail() {
},
{
title: "Flow",
onClick: () => {
setIsFlowTabOpenend(true);
getCertificateChainDetails();
},
content: certificateNodes.length ? (
<FlowChart
busy={isBusy}
flowChartTitle="Certificate Flow"
flowChartEdges={certificateEdges}
flowChartNodes={certificateNodes}
Expand Down
6 changes: 5 additions & 1 deletion src/components/_pages/certificates/list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,11 @@ export default function CertificateList({
certificate.serialNumber || "",
certificate.signatureAlgorithm,
certificate.publicKeyAlgorithm,
certificate.issuerCommonName || "",
certificate.issuerCommonName ? (
<Link to={`./detail/${certificate.issuerCertificateUuid}`}>{certificate.issuerCommonName}</Link>
) : (
""
),
certificate.certificateType ? (
<Badge color={certificate.certificateType === CertificateType.X509 ? "primary" : "secondary"}>
{getEnumLabel(certificateTypeEnum, certificate.certificateType)}
Expand Down
21 changes: 21 additions & 0 deletions src/ducks/certificates-epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,26 @@ const listCertificateApprovals: AppEpic = (action$, state$, deps) => {
);
};

const getCertificateChain: AppEpic = (action$, state$, deps) => {
return action$.pipe(
filter(slice.actions.getCertificateChain.match),
switchMap((action) =>
deps.apiClients.certificates.getCertificateChain(action.payload).pipe(
map((response) => slice.actions.getCertificateChainSuccess({ certificateChain: response })),

catchError((error) =>
of(
slice.actions.getCertificateChainFailure({
error: extractError(error, "Failed to get certificate chain"),
}),
appRedirectActions.fetchError({ error, message: "Failed to get certificate chain" }),
),
),
),
),
);
};

const epics = [
listCertificates,
getCertificateDetail,
Expand All @@ -798,6 +818,7 @@ const epics = [
getCsrAttributes,
getCertificateContent,
listCertificateApprovals,
getCertificateChain,
];

export default epics;
Loading

0 comments on commit f9da071

Please sign in to comment.