docs(nx-dev): add enterprise security page (#30852)
Introduce a new enterprise security page highlighting key features like cache poisoning protection, CI access, and personal access control.
This commit is contained in:
parent
73da211694
commit
3b0c456bbe
@ -1,6 +1,7 @@
|
||||
import {
|
||||
AgentNumberOverTime,
|
||||
AutomatedAgentsManagement,
|
||||
EnhancedSecurity,
|
||||
EnhancedWithAi,
|
||||
FasterAndCheaper,
|
||||
Hero,
|
||||
@ -61,6 +62,9 @@ export default function NxCloudPage(): ReactElement {
|
||||
<div className="mt-32 lg:mt-56">
|
||||
<FasterAndCheaper />
|
||||
</div>
|
||||
<div className="mt-32 lg:mt-56">
|
||||
<EnhancedSecurity />
|
||||
</div>
|
||||
<div className="mt-32 lg:mt-56">
|
||||
<UnderstandWorkspace />
|
||||
</div>
|
||||
|
||||
86
nx-dev/nx-dev/pages/enterprise/security.tsx
Normal file
86
nx-dev/nx-dev/pages/enterprise/security.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import { NextSeo } from 'next-seo';
|
||||
import {
|
||||
ButtonLinkProps,
|
||||
DefaultLayout,
|
||||
Footer,
|
||||
Header,
|
||||
} from '@nx/nx-dev/ui-common';
|
||||
import {
|
||||
BuiltForEnterprise,
|
||||
CachePoisoningProtection,
|
||||
CiAccess,
|
||||
FailingCompliance,
|
||||
PersonalAccess,
|
||||
SecurityCallToAction,
|
||||
SecurityHero,
|
||||
WhyCiSecurityMatters,
|
||||
} from '@nx/nx-dev/ui-enterprise';
|
||||
import { type ReactElement } from 'react';
|
||||
|
||||
export function EnterpriseSecurity(): ReactElement {
|
||||
const router = useRouter();
|
||||
|
||||
const headerCTAConfig: ButtonLinkProps[] = [
|
||||
{
|
||||
href: '/contact',
|
||||
variant: 'secondary',
|
||||
size: 'small',
|
||||
title: 'Contact us',
|
||||
children: 'Contact us',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<NextSeo
|
||||
title="Enterprise-Grade Security, Built Into the Core"
|
||||
description="Protect your codebase from artifact poisoning with infrastructure-first security."
|
||||
canonical="https://nx.dev/enterprise/security"
|
||||
openGraph={{
|
||||
url: 'https://nx.dev' + router.asPath,
|
||||
title: 'Enterprise-Grade Security, Built Into the Core',
|
||||
description:
|
||||
'Protect your codebase from artifact poisoning with infrastructure-first security.',
|
||||
images: [
|
||||
{
|
||||
url: 'https://nx.dev/socials/nx-media.png',
|
||||
width: 800,
|
||||
height: 421,
|
||||
alt: 'Nx: Smart Monorepos · Fast CI',
|
||||
type: 'image/jpeg',
|
||||
},
|
||||
],
|
||||
siteName: 'Nx',
|
||||
type: 'website',
|
||||
}}
|
||||
/>
|
||||
<DefaultLayout headerCTAConfig={headerCTAConfig}>
|
||||
<SecurityHero />
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<WhyCiSecurityMatters />
|
||||
</div>
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<FailingCompliance />
|
||||
</div>
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<CachePoisoningProtection />
|
||||
</div>
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<PersonalAccess />
|
||||
</div>
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<CiAccess />
|
||||
</div>
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<BuiltForEnterprise />
|
||||
</div>
|
||||
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||
<SecurityCallToAction />
|
||||
</div>
|
||||
</DefaultLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnterpriseSecurity;
|
||||
@ -4,6 +4,7 @@ export * from './lib/trusted-by';
|
||||
export * from './lib/faster-and-cheaper';
|
||||
export * from './lib/understand-workspace';
|
||||
export * from './lib/enhance-with-ai';
|
||||
export * from './lib/enhanced-security';
|
||||
export * from './lib/automated-agents-management';
|
||||
export * from './lib/agent-number-over-time';
|
||||
export * from './lib/statistics';
|
||||
|
||||
92
nx-dev/ui-cloud/src/lib/enhanced-security.tsx
Normal file
92
nx-dev/ui-cloud/src/lib/enhanced-security.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import {
|
||||
CloudArrowDownIcon,
|
||||
CodeBracketIcon,
|
||||
FingerPrintIcon,
|
||||
IdentificationIcon,
|
||||
LinkSlashIcon,
|
||||
RectangleGroupIcon,
|
||||
ServerIcon,
|
||||
ServerStackIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { SectionHeading } from '@nx/nx-dev/ui-common';
|
||||
import Link from 'next/link';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
const features = [
|
||||
{
|
||||
name: 'Trusted CI Writes',
|
||||
description:
|
||||
'By default, only artifacts produced by verified CI pipelines can enter the shared cache, making cache-poisoning attacks impossible.',
|
||||
icon: ServerIcon,
|
||||
},
|
||||
{
|
||||
name: 'Artifact Traceability',
|
||||
description:
|
||||
'Every build artifact is tied to the identity and permissions of the user or process that created it, ensuring full auditability.',
|
||||
icon: FingerPrintIcon,
|
||||
},
|
||||
{
|
||||
name: 'Automatic Invalidation',
|
||||
description:
|
||||
'Revoke a compromised token and instantly render all artifacts it produced unusable.',
|
||||
icon: LinkSlashIcon,
|
||||
},
|
||||
{
|
||||
name: 'Real-Time Access Control',
|
||||
description:
|
||||
'Provision, audit, and revoke developer and CI access on the fly—integrated with your identity provider for immediate effect.',
|
||||
icon: IdentificationIcon,
|
||||
},
|
||||
];
|
||||
|
||||
export function EnhancedSecurity(): ReactElement {
|
||||
return (
|
||||
<section id="ai-for-your-ci" className="scroll-mt-24">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="mx-auto max-w-3xl text-center">
|
||||
<SectionHeading as="h2" variant="title" id="deep-understanding">
|
||||
Enterprise-grade CI Security
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
Protect your codebase from artifact poisoning with
|
||||
infrastructure-first safeguards—ensuring compliance in regulated
|
||||
industries.
|
||||
</SectionHeading>
|
||||
</div>
|
||||
<dl className="mx-auto mt-16 grid max-w-5xl grid-cols-1 gap-6 sm:mt-20 md:grid-cols-2 lg:mt-24 lg:gap-12">
|
||||
{features.map((feature) => (
|
||||
<div key={feature.name} className="relative pl-9">
|
||||
<dt className="flex items-center gap-4 text-base font-semibold leading-7 text-slate-950 dark:text-white">
|
||||
<feature.icon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 size-5 shrink-0"
|
||||
/>
|
||||
{feature.name}
|
||||
</dt>
|
||||
<dd className="mt-2 text-base leading-7">
|
||||
{feature.description}
|
||||
</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
|
||||
<div className="mt-12 text-center">
|
||||
<Link
|
||||
href="/enterprise/security"
|
||||
title="Learn more about Nx Cloud security"
|
||||
prefetch={false}
|
||||
className="group mt-4 text-sm font-semibold leading-6 text-slate-950 dark:text-white"
|
||||
>
|
||||
See what we do to keep you secure{' '}
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="inline-block transition group-hover:translate-x-1"
|
||||
>
|
||||
→
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@ -25,7 +25,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { ButtonLink, ButtonLinkProps } from '../button';
|
||||
import { resourceMenuItems } from './menu-items';
|
||||
import { enterpriseItems, resourceMenuItems } from './menu-items';
|
||||
import { MobileMenuItem } from './mobile-menu-item';
|
||||
import { SectionsMenu } from './sections-menu';
|
||||
import { AlgoliaSearch } from '@nx/nx-dev/feature-search';
|
||||
@ -186,14 +186,49 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
|
||||
Pricing
|
||||
</Link>
|
||||
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
|
||||
<Link
|
||||
href="/enterprise"
|
||||
title="Nx Enterprise"
|
||||
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
|
||||
prefetch={false}
|
||||
>
|
||||
Enterprise
|
||||
</Link>
|
||||
<Popover className="relative">
|
||||
{({ open }) => (
|
||||
<>
|
||||
<PopoverButton
|
||||
className={cx(
|
||||
open ? 'text-blue-500 dark:text-sky-500' : '',
|
||||
'group inline-flex items-center px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
|
||||
)}
|
||||
>
|
||||
<span className="transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500">
|
||||
Enterprise
|
||||
</span>
|
||||
<ChevronDownIcon
|
||||
className={cx(
|
||||
open
|
||||
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
|
||||
: '',
|
||||
'ml-2 h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</PopoverButton>
|
||||
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-200"
|
||||
enterFrom="opacity-0 translate-y-1"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in duration-150"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-1"
|
||||
>
|
||||
<Popover.Panel className="absolute left-60 z-30 mt-3 w-max max-w-2xl -translate-x-1/2 transform lg:left-20">
|
||||
<SectionsMenu
|
||||
sections={{
|
||||
'Nx for Enterprises': enterpriseItems,
|
||||
}}
|
||||
/>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Popover>
|
||||
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
|
||||
<div className="px-3 opacity-50 hover:opacity-100">
|
||||
<AlgoliaSearch tiny={true} />
|
||||
@ -407,14 +442,44 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
|
||||
>
|
||||
Remote Cache
|
||||
</Link>
|
||||
<Link
|
||||
href="/enterprise"
|
||||
title="Enterprise"
|
||||
className="flex w-full gap-2 py-4 font-medium leading-tight hover:text-blue-500 dark:text-slate-200 dark:hover:text-sky-500"
|
||||
prefetch={false}
|
||||
>
|
||||
Enterprise
|
||||
</Link>
|
||||
<Disclosure as="div">
|
||||
{({ open }) => (
|
||||
<>
|
||||
<DisclosureButton
|
||||
className={cx(
|
||||
open
|
||||
? 'text-blue-500 dark:text-sky-500'
|
||||
: 'tex-slate-800 dark:text-slate-200',
|
||||
'flex w-full items-center justify-between py-4 text-left text-base font-medium focus:outline-none'
|
||||
)}
|
||||
>
|
||||
<span>Enterprise</span>
|
||||
<ChevronDownIcon
|
||||
aria-hidden="true"
|
||||
className={cx(
|
||||
open
|
||||
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
|
||||
: 'tex-slate-800 dark:text-slate-200',
|
||||
'h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
|
||||
)}
|
||||
/>
|
||||
</DisclosureButton>
|
||||
<Disclosure.Panel
|
||||
as="ul"
|
||||
className="space-y-1 pb-2"
|
||||
>
|
||||
{Object.values(enterpriseItems)
|
||||
.flat()
|
||||
.map((item) => (
|
||||
<MobileMenuItem
|
||||
key={item.name}
|
||||
item={item}
|
||||
/>
|
||||
))}
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
<Link
|
||||
href="/contact"
|
||||
title="Contact"
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
CheckBadgeIcon,
|
||||
LifebuoyIcon,
|
||||
BookOpenIcon,
|
||||
ShieldCheckIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { FC, SVGProps } from 'react';
|
||||
import { DiscordIcon } from '../discord-icon';
|
||||
@ -147,35 +148,6 @@ export const ossProducts: MenuItem[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const enterpriseProducts: MenuItem[] = [
|
||||
{
|
||||
name: 'Nx Cloud',
|
||||
description:
|
||||
'Nx Cloud is the end-to-end solution for smart, efficient and maintainable CI',
|
||||
href: '/nx-cloud',
|
||||
icon: null,
|
||||
isNew: false,
|
||||
isHighlight: false,
|
||||
},
|
||||
{
|
||||
name: 'Nx Powerpack',
|
||||
description:
|
||||
'A suite of paid extensions for the Nx CLI specifically designed for enterprises.',
|
||||
href: '/powerpack',
|
||||
icon: null,
|
||||
isNew: false,
|
||||
isHighlight: false,
|
||||
},
|
||||
{
|
||||
name: 'Nx Enterprise',
|
||||
description:
|
||||
"Accelerate your organization's journey to tighter collaboration, better developer experience, and speed…lots of speed.",
|
||||
href: '/enterprise',
|
||||
icon: null,
|
||||
isNew: false,
|
||||
isHighlight: false,
|
||||
},
|
||||
];
|
||||
export const learnItems: MenuItem[] = [
|
||||
{
|
||||
name: 'Step by step tutorials',
|
||||
@ -287,6 +259,26 @@ export const companyItems: MenuItem[] = [
|
||||
isHighlight: false,
|
||||
},
|
||||
];
|
||||
export const enterpriseItems: MenuItem[] = [
|
||||
{
|
||||
name: 'Solutions',
|
||||
description:
|
||||
"Accelerate your organization's journey to tighter collaboration, better developer experience, and speed.",
|
||||
href: '/enterprise',
|
||||
icon: BuildingOfficeIcon,
|
||||
isNew: false,
|
||||
isHighlight: false,
|
||||
},
|
||||
{
|
||||
name: 'Security',
|
||||
description:
|
||||
'Protect your codebase from artifact poisoning with infrastructure-first security.',
|
||||
icon: ShieldCheckIcon,
|
||||
href: '/enterprise/security',
|
||||
isNew: false,
|
||||
isHighlight: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const resourceMenuItems = {
|
||||
Learn: learnItems,
|
||||
|
||||
@ -11,3 +11,11 @@ export * from './lib/testimonial-carousel';
|
||||
export * from './lib/download-case-study';
|
||||
export * from './lib/trial-nx-enterprise';
|
||||
export * from './lib/enterprise-layout';
|
||||
export * from './lib/security/cache-poisoning-protection';
|
||||
export * from './lib/security/why-ci-security-matters';
|
||||
export * from './lib/security/hero';
|
||||
export * from './lib/security/personal-access';
|
||||
export * from './lib/security/ci-access';
|
||||
export * from './lib/security/build-for-enterprise';
|
||||
export * from './lib/security/call-to-action';
|
||||
export * from './lib/security/failing-compliance';
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import {
|
||||
BuildingOfficeIcon,
|
||||
GlobeAmericasIcon,
|
||||
ServerStackIcon,
|
||||
ShieldCheckIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { SectionHeading } from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export function Security(): ReactElement {
|
||||
return (
|
||||
@ -99,6 +101,31 @@ export function Security(): ReactElement {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 flex gap-4">
|
||||
<BuildingOfficeIcon
|
||||
aria-hidden="true"
|
||||
className="size-6 shrink-0"
|
||||
/>
|
||||
<div>
|
||||
<h4 className="relative text-base font-medium leading-6 text-slate-900 dark:text-slate-100">
|
||||
Enterprise-grade CI security
|
||||
</h4>
|
||||
<p className="mt-2">
|
||||
Protect your codebase from artifact poisoning with
|
||||
infrastructure-first-safeguards, ensuring compliance in
|
||||
regulated industries (
|
||||
<Link
|
||||
href="/enterprise/security"
|
||||
title="Enterprise-grade CI security"
|
||||
className="font-semibold"
|
||||
>
|
||||
Learn more
|
||||
</Link>
|
||||
)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
'use client';
|
||||
import { SectionHeading } from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
import {
|
||||
AdobeIcon,
|
||||
AwsIcon,
|
||||
CapitalOneIcon,
|
||||
FicoIcon,
|
||||
ModernaIcon,
|
||||
PayfitIcon,
|
||||
RoyalBankOfCanadaIcon,
|
||||
} from '@nx/nx-dev/ui-icons';
|
||||
|
||||
export function BuiltForEnterprise(): ReactElement {
|
||||
return (
|
||||
<section
|
||||
id="built-for-enteprise-section"
|
||||
className="scroll-mt-24 overflow-hidden"
|
||||
>
|
||||
<div className="mx-auto max-w-7xl lg:px-8">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:grid-cols-3 lg:items-start">
|
||||
<div className="mt-4 flex flex-col justify-items-stretch gap-4 sm:px-6 lg:px-0">
|
||||
<div className="mt-12 grid w-full grid-cols-2 place-items-center gap-6">
|
||||
<CapitalOneIcon
|
||||
aria-hidden="true"
|
||||
className="col-span-1 size-28 text-black dark:text-white"
|
||||
/>
|
||||
|
||||
<FicoIcon
|
||||
aria-hidden="true"
|
||||
className="col-span-1 size-24 text-[#0A6DE6] dark:text-white"
|
||||
/>
|
||||
|
||||
<AwsIcon
|
||||
aria-hidden="true"
|
||||
className="col-span-1 size-14 text-[#FF9900] dark:text-white"
|
||||
/>
|
||||
|
||||
<ModernaIcon
|
||||
aria-hidden="true"
|
||||
className="col-span-1 size-24 text-black dark:text-white"
|
||||
/>
|
||||
|
||||
<RoyalBankOfCanadaIcon
|
||||
aria-hidden="true"
|
||||
className="col-span-1 size-14 text-black dark:text-white"
|
||||
/>
|
||||
|
||||
<AdobeIcon
|
||||
aria-hidden="true"
|
||||
className="col-span-1 size-14 text-[#FF0000] dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-2 px-6 md:px-0 lg:pr-4 lg:pt-4">
|
||||
<SectionHeading as="h2" variant="title" id="built-for-enteprise">
|
||||
Built for the Enterprise, Trusted by Leading Teams
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
Thousands of developers rely on Nx Cloud to move fast — and stay
|
||||
secure.
|
||||
</SectionHeading>
|
||||
|
||||
<figure className="mt-16 rounded-lg bg-slate-100 p-4 pl-8 dark:bg-slate-800">
|
||||
<blockquote className="text-base/7">
|
||||
<p>
|
||||
“Nx is the tool that helps gain speed and trust on the overall
|
||||
system and empowers engineers and product builders to ship
|
||||
faster → to go to market faster.”
|
||||
</p>
|
||||
</blockquote>
|
||||
<figcaption className="mt-6 flex items-center gap-x-4 text-sm/6">
|
||||
<img
|
||||
alt="avatar"
|
||||
src="https://avatars.githubusercontent.com/u/7281023?v=4"
|
||||
className="size-8 flex-none rounded-full"
|
||||
/>
|
||||
<div>
|
||||
<div className="font-semibold">Nicolas Beaussart</div>
|
||||
<div className="text-slate-500">
|
||||
Staff Platform Engineer, Payfit
|
||||
</div>
|
||||
</div>
|
||||
<PayfitIcon
|
||||
aria-hidden="true"
|
||||
className="ml-auto size-10 rounded text-[#0F6FDE] dark:text-white"
|
||||
/>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
'use client';
|
||||
import {
|
||||
FingerPrintIcon,
|
||||
LinkSlashIcon,
|
||||
ServerIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import {
|
||||
SectionDescription,
|
||||
SectionHeading,
|
||||
Strong,
|
||||
} from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
export function CachePoisoningProtection(): ReactElement {
|
||||
return (
|
||||
<section
|
||||
id="cache-poisoning-protection-section"
|
||||
className="scroll-mt-24 overflow-hidden"
|
||||
>
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-20 lg:grid-cols-2 lg:items-end">
|
||||
<div>
|
||||
<SectionHeading
|
||||
as="h2"
|
||||
variant="title"
|
||||
id="cache-poisoning-protection"
|
||||
>
|
||||
Cache Poisoning Protection, By Design
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
Protect your main branch – and your customers – from compromised
|
||||
builds.
|
||||
</SectionHeading>
|
||||
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
Most teams lock down code merges, but leave their cache wide open.
|
||||
With other tools, attackers can overwrite artifacts on the main
|
||||
branch without secrets, without cache access, and without leaving
|
||||
a trace.
|
||||
</SectionDescription>
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
In other systems, cache poisoning can silently alter frontend
|
||||
forms, backend APIs, or database access — and go undetected. With
|
||||
Nx Cloud, only trusted builds produce trusted artifacts.
|
||||
</SectionDescription>
|
||||
</div>
|
||||
<div>
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
<Strong>
|
||||
Nx Cloud makes this kind of attack categorically impossible by
|
||||
implementing:
|
||||
</Strong>
|
||||
</SectionDescription>
|
||||
|
||||
<ul className="mt-4 space-y-4 text-base leading-7">
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ServerIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Writes only from trusted CI{' '}
|
||||
</span>
|
||||
– By default, the cache artifacts are reused within each pull
|
||||
request. Only artifacts from verified CI pipelines can enter the
|
||||
shared cache used by everyone. PR environments can’t poison
|
||||
main.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<FingerPrintIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Artifact traceability{' '}
|
||||
</span>
|
||||
– Artifacts are tied to the identity and permissions of the user
|
||||
or process that created them.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<LinkSlashIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Automatic invalidation{' '}
|
||||
</span>
|
||||
– Revoke a token and every artifact it produced becomes
|
||||
unusable.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
86
nx-dev/ui-enterprise/src/lib/security/call-to-action.tsx
Normal file
86
nx-dev/ui-enterprise/src/lib/security/call-to-action.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import Link from 'next/link';
|
||||
import { ReactElement } from 'react';
|
||||
import { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
|
||||
|
||||
export function SecurityCallToAction(): ReactElement {
|
||||
return (
|
||||
<section
|
||||
className="relative isolate px-6 py-32 sm:py-40 lg:px-8"
|
||||
aria-labelledby="section-cta-heading"
|
||||
>
|
||||
<svg
|
||||
className="absolute inset-0 -z-10 h-full w-full rotate-180 stroke-black/10 [mask-image:radial-gradient(100%_100%_at_top_right,white,transparent)] dark:stroke-white/10"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id="1d4240dd-898f-445f-932d-e2872fd12de3"
|
||||
width={200}
|
||||
height={200}
|
||||
x="50%"
|
||||
y={0}
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<path d="M.5 200V.5H200" fill="none" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<svg
|
||||
x="50%"
|
||||
y={0}
|
||||
className="overflow-visible fill-slate-200/20 dark:fill-slate-800/20"
|
||||
>
|
||||
<path
|
||||
d="M-200 0h201v201h-201Z M600 0h201v201h-201Z M-400 600h201v201h-201Z M200 800h201v201h-201Z"
|
||||
strokeWidth={0}
|
||||
/>
|
||||
</svg>
|
||||
<rect
|
||||
width="100%"
|
||||
height="100%"
|
||||
strokeWidth={0}
|
||||
fill="url(#1d4240dd-898f-445f-932d-e2872fd12de3)"
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
className="absolute inset-x-0 top-10 -z-10 flex transform-gpu justify-center overflow-hidden blur-3xl"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className="aspect-[1108/632] w-[69.25rem] flex-none bg-gradient-to-r from-[#80caff] to-[#4f46e5] opacity-10"
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(73.6% 51.7%, 91.7% 11.8%, 100% 46.4%, 97.4% 82.2%, 92.5% 84.9%, 75.7% 64%, 55.3% 47.5%, 46.5% 49.4%, 45% 62.9%, 50.3% 87.2%, 21.3% 64.1%, 0.1% 100%, 5.4% 51.1%, 21.4% 63.9%, 58.9% 0.2%, 73.6% 51.7%)',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mx-auto max-w-2xl text-center">
|
||||
<h2
|
||||
id="section-cta-heading"
|
||||
className="text-3xl font-medium tracking-tight text-slate-950 sm:text-5xl dark:text-white"
|
||||
>
|
||||
Security that scales <br className="hidden lg:block" /> with your team
|
||||
</h2>
|
||||
<div className="mt-10">
|
||||
<p className="mt-6 italic">
|
||||
<Link
|
||||
href="/contact/sales"
|
||||
title="Talk to an expert"
|
||||
prefetch={false}
|
||||
onClick={() =>
|
||||
sendCustomEvent(
|
||||
'contact-team',
|
||||
'enterprise-security-bottom-cta',
|
||||
'enterprise-security'
|
||||
)
|
||||
}
|
||||
className="rounded-md bg-slate-950 px-3.5 py-2.5 text-sm font-semibold text-slate-100 shadow-sm hover:bg-slate-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white dark:bg-white dark:text-slate-900 dark:hover:bg-slate-100"
|
||||
>
|
||||
Talk to an expert
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
86
nx-dev/ui-enterprise/src/lib/security/ci-access.tsx
Normal file
86
nx-dev/ui-enterprise/src/lib/security/ci-access.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
'use client';
|
||||
import {
|
||||
ArrowPathIcon,
|
||||
ArrowsUpDownIcon,
|
||||
FingerPrintIcon,
|
||||
IdentificationIcon,
|
||||
LinkSlashIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import {
|
||||
SectionDescription,
|
||||
SectionHeading,
|
||||
Strong,
|
||||
} from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
import { GitHubIcon } from '@nx/nx-dev/ui-icons';
|
||||
import Link from 'next/link';
|
||||
|
||||
export function CiAccess(): ReactElement {
|
||||
return (
|
||||
<section
|
||||
id="token-rotation-and-revocation-section"
|
||||
className="scroll-mt-24 overflow-hidden"
|
||||
>
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-20 lg:grid-cols-2 lg:items-end">
|
||||
<div>
|
||||
<SectionHeading
|
||||
as="h2"
|
||||
variant="title"
|
||||
id="token-rotation-and-revocation"
|
||||
>
|
||||
CI Access: Token Rotation & Revocation
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
Secure today, safer tomorrow: automatic token rotation.
|
||||
</SectionHeading>
|
||||
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
<Strong>
|
||||
Compromised token? Those artifacts won’t touch production.
|
||||
</Strong>{' '}
|
||||
All artifacts created with a revoked token are automatically
|
||||
invalidated — so leaked credentials can’t poison your builds.
|
||||
</SectionDescription>
|
||||
</div>
|
||||
<div>
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
<Strong>Nx Cloud allows you to:</Strong>
|
||||
</SectionDescription>
|
||||
<ul className="mt-4 space-y-4 text-base leading-7">
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ArrowPathIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Rotate tokens weekly (or as often as needed)
|
||||
</span>
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ArrowsUpDownIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Minimize long-term exposure with read-write token rotations
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="mt-4">
|
||||
<Link
|
||||
href="/ci/recipes/security/access-tokens"
|
||||
title="Learn more about CI Access Tokens"
|
||||
className="text-sm/6 font-semibold"
|
||||
>
|
||||
Learn more about CI Access Tokens{' '}
|
||||
<span aria-hidden="true">→</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
154
nx-dev/ui-enterprise/src/lib/security/failing-compliance.tsx
Normal file
154
nx-dev/ui-enterprise/src/lib/security/failing-compliance.tsx
Normal file
@ -0,0 +1,154 @@
|
||||
'use client';
|
||||
import {
|
||||
BugAntIcon,
|
||||
DocumentCheckIcon,
|
||||
ExclamationTriangleIcon,
|
||||
EyeSlashIcon,
|
||||
FingerPrintIcon,
|
||||
LinkSlashIcon,
|
||||
ServerIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import {
|
||||
ButtonLink,
|
||||
SectionDescription,
|
||||
SectionHeading,
|
||||
Strong,
|
||||
} from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export function FailingCompliance(): ReactElement {
|
||||
return (
|
||||
<section id="compliance-section" className="scroll-mt-24">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-20 lg:grid-cols-2 lg:items-end">
|
||||
<div>
|
||||
<SectionHeading as="h2" variant="title" id="compliance">
|
||||
Rolling Your Own Cache Fails in Regulated Sectors
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
Unmanaged caching may be convenient now—but it’s a liability down
|
||||
the road.
|
||||
</SectionHeading>
|
||||
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
If you operate in a regulated sector—
|
||||
<Strong>
|
||||
finance, healthcare, government, defense, aerospace, or
|
||||
pharmaceuticals
|
||||
</Strong>
|
||||
—self-hosting your remote cache may expose you to{' '}
|
||||
<Strong>serious risks like cache poisoning</Strong>.
|
||||
</SectionDescription>
|
||||
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
These community-built cache solutions all too often miss essential
|
||||
safeguards—no integrity validation, no fine-grained access
|
||||
controls, and no real-time token revocation:
|
||||
</SectionDescription>
|
||||
|
||||
<ul className="mt-4 list-disc space-y-1 pl-6 text-base leading-7">
|
||||
<li className="">nx-remotecache-azure</li>
|
||||
<li className="">turborepo-remote-cache</li>
|
||||
<li className="">nx-cache-server</li>
|
||||
<li className="">turborepo-remote-cache-cloudflare</li>
|
||||
<li className="">and others like them</li>
|
||||
</ul>
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
Our{' '}
|
||||
<Link
|
||||
href="/remote-cache"
|
||||
title="official Nx self-hosted plugin"
|
||||
className="font-semibold underline"
|
||||
>
|
||||
official Nx self-hosted plugin
|
||||
</Link>{' '}
|
||||
adds enhanced security but follows a similar architecture to the
|
||||
packages above. It is unable to make guarantees about how cache
|
||||
artifacts are secured or accessed and cannot meet the security
|
||||
demands of regulated industries.
|
||||
</SectionDescription>
|
||||
</div>
|
||||
<div>
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
<Strong>
|
||||
Failing to secure your cache can lead to steep breach fines, SLA
|
||||
breaches, damaged reputation, and costly audit delays.
|
||||
</Strong>
|
||||
</SectionDescription>
|
||||
|
||||
<ul className="mt-6 space-y-4 text-base leading-7">
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ExclamationTriangleIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
SOC 2:{' '}
|
||||
</span>
|
||||
Self-hosted caches lack independent audits, continuous
|
||||
monitoring, and incident response documentation required for SOC
|
||||
2 compliance.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ExclamationTriangleIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
HIPAA:{' '}
|
||||
</span>
|
||||
No administrative, physical, or technical safeguards to meet
|
||||
HIPAA mandates for protecting ePHI.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ExclamationTriangleIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
ISO 27001:{' '}
|
||||
</span>
|
||||
Cannot prove a certified ISMS, risk-management processes, or
|
||||
internal/external audit cycles.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ExclamationTriangleIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
FedRAMP:{' '}
|
||||
</span>
|
||||
Not authorized for federal use; missing mandatory controls for
|
||||
data classification, monitoring, and secure U.S. hosting.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<ExclamationTriangleIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
PCI-DSS:{' '}
|
||||
</span>
|
||||
No encryption, segmentation, or logging controls to safeguard
|
||||
cardholder data.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="mt-10 text-center">
|
||||
<ButtonLink
|
||||
href="/contact/sales"
|
||||
variant="primary"
|
||||
size="default"
|
||||
title="Talk to an expert"
|
||||
>
|
||||
Talk to an expert
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
21
nx-dev/ui-enterprise/src/lib/security/hero.tsx
Normal file
21
nx-dev/ui-enterprise/src/lib/security/hero.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
'use client';
|
||||
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement, useState, useEffect } from 'react';
|
||||
import { Dialog, DialogPanel, Transition } from '@headlessui/react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export function SecurityHero(): ReactElement {
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="mx-auto max-w-2xl text-center xl:max-w-6xl">
|
||||
<SectionHeading as="h1" variant="display">
|
||||
Enterprise-Grade Security, Built Into the Core
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6 text-center">
|
||||
Protect your codebase from artifact poisoning with
|
||||
infrastructure-first security.
|
||||
</SectionHeading>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
94
nx-dev/ui-enterprise/src/lib/security/personal-access.tsx
Normal file
94
nx-dev/ui-enterprise/src/lib/security/personal-access.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
'use client';
|
||||
import {
|
||||
FingerPrintIcon,
|
||||
IdentificationIcon,
|
||||
LinkSlashIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import {
|
||||
SectionDescription,
|
||||
SectionHeading,
|
||||
Strong,
|
||||
} from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
import { GitHubIcon } from '@nx/nx-dev/ui-icons';
|
||||
import Link from 'next/link';
|
||||
|
||||
export function PersonalAccess(): ReactElement {
|
||||
return (
|
||||
<section
|
||||
id="control-access-in-real-time-section"
|
||||
className="scroll-mt-24 overflow-hidden"
|
||||
>
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-20 lg:grid-cols-2 lg:items-start">
|
||||
<div>
|
||||
<SectionHeading
|
||||
as="h2"
|
||||
variant="title"
|
||||
id="control-access-in-real-time"
|
||||
>
|
||||
Personal Access: Control Access in Real Time
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
Provision, audit, and revoke with confidence.
|
||||
</SectionHeading>
|
||||
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
Easily manage developer access to your Nx Cloud workspace — no
|
||||
waiting, no lingering access for former teammates or contractors.
|
||||
</SectionDescription>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
<Strong>Nx Cloud ensures:</Strong>
|
||||
</SectionDescription>
|
||||
|
||||
<ul className="mt-4 space-y-4 text-base leading-7">
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<IdentificationIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Access is tied to individual user authentication
|
||||
</span>
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<GitHubIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Access is tied to your identity provider{' '}
|
||||
</span>
|
||||
— when SSO or GitHub access is revoked, cache access is too.
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<LinkSlashIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Token revocation cuts off access in real time
|
||||
</span>
|
||||
, and invalidates any artifacts they produced.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="mt-4">
|
||||
<Link
|
||||
href="/ci/recipes/security/personal-access-tokens"
|
||||
title="Learn more about Personal Access Tokens"
|
||||
className="text-sm/6 font-semibold"
|
||||
>
|
||||
Learn more about Personal Access Tokens{' '}
|
||||
<span aria-hidden="true">→</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
'use client';
|
||||
import {
|
||||
BugAntIcon,
|
||||
DocumentCheckIcon,
|
||||
EyeSlashIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import {
|
||||
ButtonLink,
|
||||
SectionDescription,
|
||||
SectionHeading,
|
||||
Strong,
|
||||
} from '@nx/nx-dev/ui-common';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
export function WhyCiSecurityMatters(): ReactElement {
|
||||
return (
|
||||
<section
|
||||
id="why-ci-security-matters-section"
|
||||
className="scroll-mt-24 overflow-hidden"
|
||||
>
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-20 lg:grid-cols-2 lg:items-end">
|
||||
<div>
|
||||
<SectionHeading
|
||||
as="h2"
|
||||
variant="title"
|
||||
id="why-ci-security-matters"
|
||||
>
|
||||
Why CI Security Matters
|
||||
</SectionHeading>
|
||||
<SectionHeading as="p" variant="subtitle" className="mt-6">
|
||||
CI pipelines are a growing target – and your cache is a critical
|
||||
entry point.
|
||||
</SectionHeading>
|
||||
|
||||
<SectionDescription as="p" className="mt-6">
|
||||
Modern build pipelines involve many contributors and moving parts.
|
||||
As your team evolves, it's essential to lock down access and
|
||||
prevent vulnerabilities like cache poisoning or unauthorized reuse
|
||||
of build data.
|
||||
</SectionDescription>
|
||||
<div className="mt-10 text-center">
|
||||
<ButtonLink
|
||||
href="/enterprise"
|
||||
variant="primary"
|
||||
size="default"
|
||||
title="Learn about Nx Cloud for Enterprises"
|
||||
>
|
||||
Learn about Nx Cloud for Enterprises
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ul className="mt-12 space-y-4 text-base leading-7">
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<BugAntIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Build artifacts can be compromised and deployed{' '}
|
||||
</span>
|
||||
– if left unprotected
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<EyeSlashIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Revoked access must take effect immediately{' '}
|
||||
</span>
|
||||
</li>
|
||||
<li className="relative pl-9">
|
||||
<span className="inline font-semibold text-slate-950 dark:text-white">
|
||||
<DocumentCheckIcon
|
||||
aria-hidden="true"
|
||||
className="absolute left-1 top-1 h-5 w-5"
|
||||
/>
|
||||
Self-hosted caching can't guarantee artifact integrity.{' '}
|
||||
</span>
|
||||
Without strict branch isolation, access control, and rebuild
|
||||
policies, poisoned artifacts can silently reach production.{' '}
|
||||
<Strong>
|
||||
For teams in highly regulated industries where undetected
|
||||
modifications are unacceptable, the risk is too high.
|
||||
</Strong>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
'use client';
|
||||
import { ReactElement } from 'react';
|
||||
import { CheckCircleIcon } from '@heroicons/react/24/solid';
|
||||
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
|
||||
import { ButtonLink, SectionHeading } from '@nx/nx-dev/ui-common';
|
||||
import { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
|
||||
import Link from 'next/link';
|
||||
import { ExclamationCircleIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
export function RemoteCacheSolutions(): ReactElement {
|
||||
return (
|
||||
@ -59,6 +60,24 @@ export function RemoteCacheSolutions(): ReactElement {
|
||||
/>
|
||||
<span>Free plans available, no credit card required</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<CheckCircleIcon
|
||||
aria-hidden="true"
|
||||
className="h-6 w-5 flex-none text-blue-600 dark:text-sky-500"
|
||||
/>
|
||||
<span>
|
||||
Secure against cache poisoning (
|
||||
<Link
|
||||
href="/enterprise/security"
|
||||
prefetch={false}
|
||||
title="Remote caching security"
|
||||
className="font-semibold underline"
|
||||
>
|
||||
Learn more
|
||||
</Link>
|
||||
)
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<CheckCircleIcon
|
||||
aria-hidden="true"
|
||||
@ -75,6 +94,7 @@ export function RemoteCacheSolutions(): ReactElement {
|
||||
Hosted on Nx Cloud servers or on-premise with{' '}
|
||||
<Link
|
||||
href="/enterprise"
|
||||
prefetch={false}
|
||||
title="Learn about Nx Enterprise"
|
||||
className="font-semibold underline"
|
||||
>
|
||||
@ -91,13 +111,6 @@ export function RemoteCacheSolutions(): ReactElement {
|
||||
Enterprise grade access management and key revocation
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<CheckCircleIcon
|
||||
aria-hidden="true"
|
||||
className="h-6 w-5 flex-none text-blue-600 dark:text-sky-500"
|
||||
/>
|
||||
<span>Secure against cache poisoning</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<CheckCircleIcon
|
||||
aria-hidden="true"
|
||||
@ -175,6 +188,25 @@ export function RemoteCacheSolutions(): ReactElement {
|
||||
/>
|
||||
<span>Free for all users</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<ExclamationCircleIcon
|
||||
aria-hidden="true"
|
||||
className="h-6 w-5 flex-none text-blue-600 dark:text-sky-500"
|
||||
/>
|
||||
<span>
|
||||
Not recommended for organizations requiring HIPAA or SOC-2
|
||||
compliance (
|
||||
<Link
|
||||
href="/enterprise/security"
|
||||
prefetch={false}
|
||||
title="Remote caching security"
|
||||
className="font-semibold underline"
|
||||
>
|
||||
Learn more
|
||||
</Link>
|
||||
)
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<CheckCircleIcon
|
||||
aria-hidden="true"
|
||||
@ -198,23 +230,6 @@ export function RemoteCacheSolutions(): ReactElement {
|
||||
Simple migration path from existing 3rd party plugins
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||
<CheckCircleIcon
|
||||
aria-hidden="true"
|
||||
className="h-6 w-5 flex-none text-blue-600 dark:text-sky-500"
|
||||
/>
|
||||
<span>
|
||||
SOC-2 compliant (
|
||||
<a
|
||||
href="https://security.nx.app/"
|
||||
title="Check our SOC 2 security report"
|
||||
className="font-semibold underline"
|
||||
>
|
||||
view report
|
||||
</a>
|
||||
)
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user