Skip to content

Commit

Permalink
[fix] Azure or other cloud Resources (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
sijav authored Aug 6, 2024
1 parent 870a4b9 commit 25e7885
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 185 deletions.
138 changes: 74 additions & 64 deletions src/locales/de-DE/messages.po

Large diffs are not rendered by default.

138 changes: 74 additions & 64 deletions src/locales/en-US/messages.po

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useUserProfile } from 'src/core/auth'
import { getWorkspaceInventorySearchStartQuery } from 'src/pages/panel/shared/queries'
import { sendInventoryError } from 'src/pages/panel/shared/utils'
import { DefaultPropertiesKeys, Predicate, useFixQueryParser } from 'src/shared/fix-query-parser'
import { getAccountCloudName } from 'src/shared/utils/getAccountCloudName'
import { InventoryFormAccount } from './InventoryFormAccount'
import { InventoryFormCloud } from './InventoryFormCloud'
import { InventoryFormFullTextSearches } from './InventoryFormFullTextSearch'
Expand Down Expand Up @@ -184,8 +185,8 @@ export const InventoryForm = ({ withChanges }: InventoryFormProps) => {
severities: processedStartData.severity.map((severity) => ({ label: severity, value: severity, id: severity })),
clouds:
(!numberOfCloudFilterSelected && selectedClouds.length) || (numberOfCloudFilterSelected && numberOfCloudSelected)
? selectedClouds.map((cloud) => ({ label: cloud.toUpperCase(), value: cloud, id: cloud }))
: processedStartData.clouds.map((cloud) => ({ value: cloud, label: cloud.toUpperCase(), id: cloud })),
? selectedClouds.map((cloud) => ({ label: getAccountCloudName(cloud), value: cloud, id: cloud }))
: processedStartData.clouds.map((cloud) => ({ value: cloud, label: getAccountCloudName(cloud), id: cloud })),
}),
[processedStartData, selectedClouds, numberOfCloudFilterSelected, numberOfCloudSelected],
)
Expand Down
90 changes: 57 additions & 33 deletions src/pages/panel/resource-detail/ResourceDetailView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Trans } from '@lingui/macro'
import { t, Trans } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import CloseIcon from '@mui/icons-material/Close'
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
Expand All @@ -16,9 +16,9 @@ import {
Skeleton,
Slide,
Stack,
styled,
Tooltip,
Typography,
styled,
} from '@mui/material'
import { useQuery } from '@tanstack/react-query'
import { AxiosError } from 'axios'
Expand All @@ -32,9 +32,11 @@ import { useAbsoluteNavigate } from 'src/shared/absolute-navigate'
import { NetworkDiagram } from 'src/shared/charts'
import { CloudAvatar } from 'src/shared/cloud-avatar'
import { panelUI } from 'src/shared/constants'
import { ExternalLinkButton } from 'src/shared/link-button'
import { Modal as PopupModal } from 'src/shared/modal'
import { StickyAccordionSummaryWithIcon } from 'src/shared/sticky-accordion-summary'
import { FailedCheck } from 'src/shared/types/server-shared'
import { AccountCloud, FailedCheck } from 'src/shared/types/server-shared'
import { getAccountCloudName } from 'src/shared/utils/getAccountCloudName'
import { diffDateTimeToDuration, iso8601DurationToString } from 'src/shared/utils/parseDuration'
import { getLocationSearchValues, removeLocationSearchValues } from 'src/shared/utils/windowLocationSearch'
import { YamlHighlighter } from 'src/shared/yaml-highlighter'
Expand Down Expand Up @@ -86,7 +88,6 @@ const GridItem = ({ property, value, color, isReactNode }: GridItemProps) => {
(value as ReactNode)
) : (
<Tooltip
arrow
slotProps={{ tooltip: { sx: { maxWidth: '100vw', maxHeight: '100vh', overflow: 'auto', p: 1 } } }}
title={
isSimpleValue ? (
Expand Down Expand Up @@ -117,6 +118,19 @@ const GridItem = ({ property, value, color, isReactNode }: GridItemProps) => {
)
}

const getOpenResourceButtonText = (cloud: AccountCloud) => {
switch (cloud) {
case 'aws':
return t`in AWS Console`
case 'azure':
return t`in Azure Portal`
case 'gcp':
return t`in Google Cloud Console`
default:
return ''
}
}

export default function ResourceDetailView() {
const postHog = usePostHog()
const { resourceDetailId } = useParams<'resourceDetailId'>()
Expand Down Expand Up @@ -166,6 +180,8 @@ export default function ResourceDetailView() {
const cloud =
data?.resource.ancestors?.cloud?.reported?.name ??
(window.decodeURIComponent(getLocationSearchValues(window.location.search)?.cloud || '') || '-')
const cloudName = getAccountCloudName(cloud)
const buttonName = getOpenResourceButtonText(cloud)
const accountObj = data?.resource.ancestors?.account?.reported
const account = accountObj ? `${accountObj?.name} (${accountObj?.id})` : '-'
const region = data?.resource.ancestors?.region?.reported?.name ?? '-'
Expand Down Expand Up @@ -235,7 +251,7 @@ export default function ResourceDetailView() {
<GridItem property={<Trans>Name</Trans>} value={name} />
<GridItem
property={<Trans>Cloud</Trans>}
value={cloud !== '-' ? <Typography>{cloud.toUpperCase()}</Typography> : '-'}
value={cloud !== '-' ? <Typography>{cloudName}</Typography> : '-'}
isReactNode={cloud !== '-'}
/>
<GridItem property={<Trans>Account</Trans>} value={account} />
Expand All @@ -253,34 +269,42 @@ export default function ResourceDetailView() {
</Grid>
<Stack direction="row" justifyContent="end" mt={2}>
{provider_link ? (
<>
<PopupModal
openRef={openResourceModalRef}
title={<Trans>Open resource {name} in AWS Console</Trans>}
width={panelUI.minLargeModalWidth}
actions={
<Button
variant="outlined"
href={provider_link}
target="_blank"
rel="noopener noreferrer"
onClick={() => openResourceModalRef.current?.(false)}
endIcon={<OpenInNewIcon />}
>
<Trans>See this Resource in AWS Console</Trans>
</Button>
}
>
<Alert severity="warning">
<AlertTitle>
<Trans>To access this resource, please ensure that you are logged into the AWS account: {account}</Trans>
</AlertTitle>
</Alert>
</PopupModal>
<Button variant="contained" onClick={() => openResourceModalRef.current?.(true)} endIcon={<OpenInNewIcon />}>
<Trans>See this Resource in AWS Console</Trans>
</Button>
</>
cloud === 'aws' ? (
<>
<PopupModal
openRef={openResourceModalRef}
title={<Trans>See this resource {buttonName}</Trans>}
width={panelUI.minLargeModalWidth}
actions={
<Button
variant="outlined"
href={provider_link}
target="_blank"
rel="noopener noreferrer"
onClick={() => openResourceModalRef.current?.(false)}
endIcon={<OpenInNewIcon />}
>
<Trans>See this resource {buttonName}</Trans>
</Button>
}
>
<Alert severity="warning">
<AlertTitle>
<Trans>
To access this resource, please ensure that you are logged into the {cloudName} account: {account}
</Trans>
</AlertTitle>
</Alert>
</PopupModal>
<Button variant="contained" onClick={() => openResourceModalRef.current?.(true)} endIcon={<OpenInNewIcon />}>
<Trans>See this resource {buttonName}</Trans>
</Button>
</>
) : (
<ExternalLinkButton href={provider_link} variant="contained">
<Trans>See this resource {buttonName}</Trans>
</ExternalLinkButton>
)
) : null}
</Stack>
</>
Expand Down
3 changes: 2 additions & 1 deletion src/pages/panel/security/AccountCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro'
import { Card, CardContent, CardHeader, Tooltip, Typography, TypographyProps, cardHeaderClasses, styled } from '@mui/material'
import { colorFromRedToGreen } from 'src/shared/constants'
import { WorkspaceAccountReportSummary } from 'src/shared/types/server'
import { getAccountCloudName } from 'src/shared/utils/getAccountCloudName'
import { shouldForwardProp } from 'src/shared/utils/shouldForwardProp'

const AccountCardContainer = styled(Card, { shouldForwardProp })<{ score?: number }>(({ theme, score }) => ({
Expand Down Expand Up @@ -34,7 +35,7 @@ export const AccountCard = ({ account }: AccountCardProps) => {
<Trans>ID</Trans>: {account.id}
</CardText>
<CardText>
<Trans>Cloud</Trans>: {account.cloud?.toUpperCase()}
<Trans>Cloud</Trans>: {account.cloud ? getAccountCloudName(account.cloud) : '-'}
</CardText>
{account.score !== undefined ? <CardText>Score: {account.score}</CardText> : undefined}
</CardContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { Modal } from 'src/shared/modal'
import { useNonce } from 'src/shared/providers'
import { GetWorkspaceInventoryReportSummaryResponse } from 'src/shared/types/server'
import { Account } from 'src/shared/types/server-shared'
import { getAccountCloudName } from 'src/shared/utils/getAccountCloudName'
import { getAccountName } from 'src/shared/utils/getAccountName'
import { deleteAccountMutation } from './deleteAccount.mutation'
import { patchAccountMutation } from './patchAccount.mutation'
Expand Down Expand Up @@ -490,7 +491,7 @@ export const WorkspaceSettingsAccountRow = ({
<Trans>ID</Trans>: {account.account_id}
</Typography>
<Typography>
<Trans>Cloud</Trans>: {account.cloud.toUpperCase()}
<Trans>Cloud</Trans>: {getAccountCloudName(account.cloud)}
</Typography>
<Typography>
<Trans>Name</Trans>: {accountName}
Expand Down
18 changes: 2 additions & 16 deletions src/shared/cloud-avatar/CloudAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ReactNode } from 'react'
import { AwsLogo, AzureLogo, Crown, FixLogo, GcpLogo } from 'src/assets/icons'
import { useNonce } from 'src/shared/providers'
import { AccountCloud } from 'src/shared/types/server-shared'
import { getAccountCloudName } from 'src/shared/utils/getAccountCloudName'

export interface CloudAvatarProps {
cloud: AccountCloud
Expand Down Expand Up @@ -36,23 +37,8 @@ const CloudIcon = ({ cloud, small, withCrown }: CloudAvatarProps) => {
}
}

const cloudDefaultTooltip = (cloud: AccountCloud) => {
switch (cloud) {
case 'aws':
return 'AWS'
case 'azure':
return 'Azure'
case 'fix':
return 'FIX'
case 'gcp':
return 'GCP'
default:
return cloud
}
}

export const CloudAvatar = ({ cloud, small, withCrown, tooltip, error, onErrorClick }: CloudAvatarProps) => (
<Tooltip title={tooltip === true ? cloudDefaultTooltip(cloud) : tooltip} arrow>
<Tooltip title={tooltip === true ? getAccountCloudName(cloud) : tooltip} arrow>
<Box position="relative">
<Box margin="0 auto">
<CloudIcon cloud={cloud} small={small} withCrown={withCrown} />
Expand Down
11 changes: 7 additions & 4 deletions src/shared/event-button/EventButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useEffect, useRef, useState } from 'react'
import { useEvents } from 'src/core/events'
import { useSnackbar } from 'src/core/snackbar'
import { WebSocketEvent } from 'src/shared/types/server'
import { getAccountCloudName } from 'src/shared/utils/getAccountCloudName'
import { EventItem } from './EventItem'

const PopperContainer = styled(Popper)(({ theme }) => ({
Expand Down Expand Up @@ -54,7 +55,7 @@ export const EventButton = () => {
void queryClient.invalidateQueries({
predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('workspace-cloud-account'),
})
void showSnackbar(t`${ev.data.cloud.toUpperCase()} Cloud account configured, id: ${ev.data.account_id}`, {
void showSnackbar(t`${getAccountCloudName(ev.data.cloud)} Cloud account configured, id: ${ev.data.account_id}`, {
severity: 'success',
autoHideDuration: null,
})
Expand All @@ -72,7 +73,7 @@ export const EventButton = () => {
void queryClient.invalidateQueries({
predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('workspace-cloud-account'),
})
void showSnackbar(t`${ev.data.cloud.toUpperCase()} Cloud account degraded, id: ${ev.data.account_id}`, {
void showSnackbar(t`${getAccountCloudName(ev.data.cloud)} Cloud account degraded, id: ${ev.data.account_id}`, {
severity: 'warning',
autoHideDuration: null,
})
Expand All @@ -81,7 +82,7 @@ export const EventButton = () => {
void queryClient.invalidateQueries({
predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('workspace-cloud-account'),
})
void showSnackbar(t`${ev.data.cloud.toUpperCase()} Cloud account degraded, id: ${ev.data.account_id}`, {
void showSnackbar(t`${getAccountCloudName(ev.data.cloud)} Cloud account degraded, id: ${ev.data.account_id}`, {
severity: 'warning',
autoHideDuration: null,
})
Expand All @@ -90,7 +91,9 @@ export const EventButton = () => {
void queryClient.invalidateQueries({
predicate: (query) => typeof query.queryKey[0] === 'string' && query.queryKey[0].startsWith('workspace-cloud-account'),
})
void showSnackbar(t`${ev.data.cloud.toUpperCase()} Cloud account discovered, id: ${ev.data.account_id}`, { severity: 'info' })
void showSnackbar(t`${getAccountCloudName(ev.data.cloud)} Cloud account discovered, id: ${ev.data.account_id}`, {
severity: 'info',
})
break
case 'aws_account_discovered':
void queryClient.invalidateQueries({
Expand Down
19 changes: 19 additions & 0 deletions src/shared/link-button/ExternalLinkButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
import { Button, ButtonProps, ButtonTypeMap } from '@mui/material'
import { ElementType } from 'react'

type ExternalLinkButtonProps<RootComponent extends ElementType, AdditionalProps> = ButtonProps<RootComponent, AdditionalProps> & {
href: string
}

export function ExternalLinkButton<RootComponent extends ElementType = ButtonTypeMap['defaultComponent'], AdditionalProps = unknown>({
href,
children,
...props
}: ExternalLinkButtonProps<RootComponent, AdditionalProps>) {
return (
<Button href={href} target="_blank" rel="noopener noreferrer" endIcon={<OpenInNewIcon fontSize="small" />} {...props}>
{children || href}
</Button>
)
}
1 change: 1 addition & 0 deletions src/shared/link-button/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { ExternalLinkButton } from './ExternalLinkButton'
export { ExternalLinkLoadingButton } from './ExternalLinkLoadingButton'
export { InternalLink } from './InternalLink'
export { InternalLinkButton } from './InternalLinkButton'
16 changes: 16 additions & 0 deletions src/shared/utils/getAccountCloudName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AccountCloud } from 'src/shared/types/server-shared'

export const getAccountCloudName = (cloud: AccountCloud) => {
switch (cloud.toLowerCase()) {
case 'aws':
return 'AWS'
case 'azure':
return 'Azure'
case 'fix':
return 'FIX'
case 'gcp':
return 'GCP'
default:
return cloud
}
}

0 comments on commit 25e7885

Please sign in to comment.