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
409 changes: 202 additions & 207 deletions api/src/locale/en/messages.po

Large diffs are not rendered by default.

409 changes: 202 additions & 207 deletions api/src/locale/fr/messages.po

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions api/src/web-scan/objects/experimental-result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLList, GraphQLObjectType, GraphQLString } from 'graphql'

export const pqcBuildRefsType = new GraphQLObjectType({
name: 'PqcBuildRefs',
fields: () => ({
nasslCommit: {
type: GraphQLString,
description: `The nassl commit the experimental environment was built from.`,
resolve: async ({ nasslCommit }) => nasslCommit,
},
sslyzeCommit: {
type: GraphQLString,
description: `The sslyze commit the experimental environment was built from.`,
resolve: async ({ sslyzeCommit }) => sslyzeCommit,
},
}),
description: `The upstream commits that produced a given experimental scan result. Version numbers are not usable here: the unreleased sslyze build reports the same version as the released one.`,
})

export const pqcResultType = new GraphQLObjectType({
name: 'PqcResult',
fields: () => ({
supportsPqKeyExchange: {
type: GraphQLBoolean,
description: `Whether the scanned server accepted at least one post-quantum hybrid key exchange group.`,
resolve: async ({ supportsPqKeyExchange }) => supportsPqKeyExchange,
},
supportedPqGroups: {
type: new GraphQLList(GraphQLString),
description: `The post-quantum hybrid key exchange groups accepted by the scanned server. Null when the server does not support TLS 1.3, in which case nothing was tested.`,
resolve: async ({ supportedPqGroups }) => supportedPqGroups,
},
tls1_3Supported: {
type: GraphQLBoolean,
description: `Whether the scanned server supports TLS 1.3, which is a prerequisite for post-quantum key exchange.`,
},
scanStatus: {
type: GraphQLString,
description: `Whether sslyze was able to complete the scan.`,
resolve: async ({ scanStatus }) => scanStatus,
},
status: {
type: GraphQLString,
description: `Whether the post-quantum scan command itself completed.`,
resolve: async ({ status }) => status,
},
error: {
type: GraphQLString,
description: `The error encountered during the scan, if any.`,
resolve: async ({ error }) => error,
},
errorReason: {
type: GraphQLString,
description: `The category of error reported by sslyze, if any.`,
resolve: async ({ errorReason }) => errorReason,
},
durationSeconds: {
type: GraphQLFloat,
description: `How long the post-quantum scan took, in seconds.`,
resolve: async ({ durationSeconds }) => durationSeconds,
},
schemaVersion: {
type: GraphQLInt,
description: `The version of the stored result shape.`,
resolve: async ({ schemaVersion }) => schemaVersion,
},
buildRefs: {
type: pqcBuildRefsType,
description: `The upstream commits that produced this result.`,
resolve: async ({ buildRefs }) => buildRefs,
},
}),
description: `Post-quantum/hybrid TLS 1.3 key exchange support, produced by an unreleased build of sslyze. Proof of concept: these values do not feed compliance scoring and the shape may change or be removed.`,
})

export const experimentalResultType = new GraphQLObjectType({
name: 'ExperimentalResult',
fields: () => ({
pqc: {
type: pqcResultType,
description: `The result of the post-quantum key exchange scan.`,
resolve: async ({ pqc }) => pqc,
},
}),
description: `Results of experimental scans. Nothing in here is a supported part of the API: fields may change or disappear without notice, and are only visible to super admins.`,
})
1 change: 1 addition & 0 deletions api/src/web-scan/objects/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './experimental-result'
export * from './tls-result'
export * from './web-scan'
export * from './web-connection-result'
Expand Down
10 changes: 10 additions & 0 deletions api/src/web-scan/objects/web-scan-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { GraphQLObjectType } from 'graphql'

import { tlsResultType } from './tls-result'
import { webConnectionResultType } from './web-connection-result'
import { experimentalResultType } from './experimental-result'
import { GraphQLDateTime } from 'graphql-scalars'

export const webScanResultType = new GraphQLObjectType({
Expand All @@ -22,6 +23,15 @@ export const webScanResultType = new GraphQLObjectType({
description: `The result for the HTTP connection scan for the scanned server.`,
resolve: async ({ connectionResults }) => connectionResults,
},
experimental: {
type: experimentalResultType,
description: `Results of experimental scans, visible to super admins only. Not a supported part of the API.`,
resolve: async ({ experimental }, __, { auth: { checkSuperAdmin } }) => {
const isSuperAdmin = await checkSuperAdmin()
if (isSuperAdmin) return experimental
return null
},
},
}),
description: `Results of TLS and HTTP connection scans on the given domain.`,
})
15 changes: 15 additions & 0 deletions frontend/src/graphql/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,21 @@ export const DOMAIN_GUIDANCE_PAGE = gql`
}
}
}
experimental {
pqc {
supportsPqKeyExchange
supportedPqGroups
tls1_3Supported
scanStatus
status
error
durationSeconds
buildRefs {
nasslCommit
sslyzeCommit
}
}
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/guidance/WebGuidance.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { array, string } from 'prop-types'
import { Trans } from "@lingui/react/macro"
import { WebTLSResults } from './WebTLSResults'
import { WebConnectionResults } from './WebConnectionResults'
import { WebPqcResults } from './WebPqcResults'
import { GuidanceSummaryCategories } from './GuidanceSummaryCategories'
import { NotificationBanner } from '../app/NotificationBanner'

Expand Down Expand Up @@ -169,7 +170,7 @@ export function WebGuidance({ webResults, timestamp }) {
</AlertDescription>
</Box>
</NotificationBanner>
<Accordion allowMultiple defaultIndex={[0, 1, 2]}>
<Accordion allowMultiple defaultIndex={[0, 1, 2, 3]}>
{timestamp && (
<Text fontSize="lg" mb="2">
<Trans>
Expand Down Expand Up @@ -214,6 +215,7 @@ export function WebGuidance({ webResults, timestamp }) {
connectionResults={currentEndpoint.results.connectionResults}
/>
<WebTLSResults tlsResult={currentEndpoint.results.tlsResult} />
<WebPqcResults pqcResult={currentEndpoint.results.experimental?.pqc} />
</>
)}
</Accordion>
Expand Down
111 changes: 111 additions & 0 deletions frontend/src/guidance/WebPqcResults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React from 'react'
import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Badge, Box, Flex, Text } from '@chakra-ui/react'
import { object } from 'prop-types'
import { Trans } from '@lingui/react/macro'
import withSuperAdmin from '../app/withSuperAdmin'

function PqcResults({ pqcResult }) {
if (!pqcResult) return null

const { supportsPqKeyExchange, supportedPqGroups, tls1_3Supported, scanStatus, status, error, buildRefs } = pqcResult

const sslyzeCommit = buildRefs?.sslyzeCommit?.slice(0, 8)
const nasslCommit = buildRefs?.nasslCommit?.slice(0, 8)

const rowProps = {
align: 'center',
borderBottomWidth: '1px',
borderBottomColor: 'gray.300',
py: '1',
}

let summary
if (error || status !== 'COMPLETED') {
summary = (
<Badge colorScheme="gray" fontSize="md">
<Trans>Not scanned</Trans>
</Badge>
)
} else if (supportsPqKeyExchange) {
summary = (
<Badge colorScheme="green" fontSize="md">
<Trans>Supported</Trans>
</Badge>
)
} else {
summary = (
<Badge colorScheme="red" fontSize="md">
<Trans>Not supported</Trans>
</Badge>
)
}

return (
<AccordionItem>
<Flex align="center" as={AccordionButton}>
<Text fontSize="2xl" mr="2">
<Trans>Post-Quantum Key Exchange</Trans>
</Text>
<Badge colorScheme="purple" fontSize="md" mr="auto">
<Trans>Experimental</Trans>
</Badge>
{summary}
<AccordionIcon boxSize="icons.xl" />
</Flex>
<AccordionPanel>
<Text mb="2">
<Trans>
Experimental result from an unreleased version of SSLyze. This does not affect compliance scoring and is
visible to super admins only.
</Trans>
</Text>

<Flex {...rowProps}>
<Text mr="auto">
<Trans>Supports post-quantum key exchange</Trans>
</Text>
<Text>{supportsPqKeyExchange ? <Trans>Yes</Trans> : <Trans>No</Trans>}</Text>
</Flex>

<Flex {...rowProps}>
<Text mr="auto">
<Trans>TLS 1.3 supported</Trans>
</Text>
<Text>{tls1_3Supported ? <Trans>Yes</Trans> : <Trans>No</Trans>}</Text>
</Flex>

<Flex {...rowProps}>
<Text mr="auto">
<Trans>Negotiated groups</Trans>
</Text>
<Text>{supportedPqGroups?.length ? supportedPqGroups.join(', ') : <Trans>None</Trans>}</Text>
</Flex>

{(error || scanStatus !== 'COMPLETED') && (
<Flex {...rowProps}>
<Text mr="auto">
<Trans>Error</Trans>
</Text>
<Text>{error || scanStatus}</Text>
</Flex>
)}

{buildRefs && (
<Box mt="2">
<Text fontSize="sm" color="gray.600">
<Trans>
Built from sslyze {sslyzeCommit} and nassl {nasslCommit}
</Trans>
</Text>
</Box>
)}
</AccordionPanel>
</AccordionItem>
)
}

PqcResults.propTypes = {
pqcResult: object,
}

export const WebPqcResults = withSuperAdmin(PqcResults)
2 changes: 1 addition & 1 deletion frontend/src/locales/en.js

Large diffs are not rendered by default.

Loading