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 {
|
import {
|
||||||
AgentNumberOverTime,
|
AgentNumberOverTime,
|
||||||
AutomatedAgentsManagement,
|
AutomatedAgentsManagement,
|
||||||
|
EnhancedSecurity,
|
||||||
EnhancedWithAi,
|
EnhancedWithAi,
|
||||||
FasterAndCheaper,
|
FasterAndCheaper,
|
||||||
Hero,
|
Hero,
|
||||||
@ -61,6 +62,9 @@ export default function NxCloudPage(): ReactElement {
|
|||||||
<div className="mt-32 lg:mt-56">
|
<div className="mt-32 lg:mt-56">
|
||||||
<FasterAndCheaper />
|
<FasterAndCheaper />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mt-32 lg:mt-56">
|
||||||
|
<EnhancedSecurity />
|
||||||
|
</div>
|
||||||
<div className="mt-32 lg:mt-56">
|
<div className="mt-32 lg:mt-56">
|
||||||
<UnderstandWorkspace />
|
<UnderstandWorkspace />
|
||||||
</div>
|
</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/faster-and-cheaper';
|
||||||
export * from './lib/understand-workspace';
|
export * from './lib/understand-workspace';
|
||||||
export * from './lib/enhance-with-ai';
|
export * from './lib/enhance-with-ai';
|
||||||
|
export * from './lib/enhanced-security';
|
||||||
export * from './lib/automated-agents-management';
|
export * from './lib/automated-agents-management';
|
||||||
export * from './lib/agent-number-over-time';
|
export * from './lib/agent-number-over-time';
|
||||||
export * from './lib/statistics';
|
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,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { ButtonLink, ButtonLinkProps } from '../button';
|
import { ButtonLink, ButtonLinkProps } from '../button';
|
||||||
import { resourceMenuItems } from './menu-items';
|
import { enterpriseItems, resourceMenuItems } from './menu-items';
|
||||||
import { MobileMenuItem } from './mobile-menu-item';
|
import { MobileMenuItem } from './mobile-menu-item';
|
||||||
import { SectionsMenu } from './sections-menu';
|
import { SectionsMenu } from './sections-menu';
|
||||||
import { AlgoliaSearch } from '@nx/nx-dev/feature-search';
|
import { AlgoliaSearch } from '@nx/nx-dev/feature-search';
|
||||||
@ -186,14 +186,49 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
|
|||||||
Pricing
|
Pricing
|
||||||
</Link>
|
</Link>
|
||||||
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
|
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
|
||||||
<Link
|
<Popover className="relative">
|
||||||
href="/enterprise"
|
{({ open }) => (
|
||||||
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"
|
<PopoverButton
|
||||||
prefetch={false}
|
className={cx(
|
||||||
>
|
open ? 'text-blue-500 dark:text-sky-500' : '',
|
||||||
Enterprise
|
'group inline-flex items-center px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
|
||||||
</Link>
|
)}
|
||||||
|
>
|
||||||
|
<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="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
|
||||||
<div className="px-3 opacity-50 hover:opacity-100">
|
<div className="px-3 opacity-50 hover:opacity-100">
|
||||||
<AlgoliaSearch tiny={true} />
|
<AlgoliaSearch tiny={true} />
|
||||||
@ -407,14 +442,44 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
|
|||||||
>
|
>
|
||||||
Remote Cache
|
Remote Cache
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Disclosure as="div">
|
||||||
href="/enterprise"
|
{({ open }) => (
|
||||||
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"
|
<DisclosureButton
|
||||||
prefetch={false}
|
className={cx(
|
||||||
>
|
open
|
||||||
Enterprise
|
? 'text-blue-500 dark:text-sky-500'
|
||||||
</Link>
|
: '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
|
<Link
|
||||||
href="/contact"
|
href="/contact"
|
||||||
title="Contact"
|
title="Contact"
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import {
|
|||||||
CheckBadgeIcon,
|
CheckBadgeIcon,
|
||||||
LifebuoyIcon,
|
LifebuoyIcon,
|
||||||
BookOpenIcon,
|
BookOpenIcon,
|
||||||
|
ShieldCheckIcon,
|
||||||
} from '@heroicons/react/24/outline';
|
} from '@heroicons/react/24/outline';
|
||||||
import { FC, SVGProps } from 'react';
|
import { FC, SVGProps } from 'react';
|
||||||
import { DiscordIcon } from '../discord-icon';
|
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[] = [
|
export const learnItems: MenuItem[] = [
|
||||||
{
|
{
|
||||||
name: 'Step by step tutorials',
|
name: 'Step by step tutorials',
|
||||||
@ -287,6 +259,26 @@ export const companyItems: MenuItem[] = [
|
|||||||
isHighlight: false,
|
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 = {
|
export const resourceMenuItems = {
|
||||||
Learn: learnItems,
|
Learn: learnItems,
|
||||||
|
|||||||
@ -11,3 +11,11 @@ export * from './lib/testimonial-carousel';
|
|||||||
export * from './lib/download-case-study';
|
export * from './lib/download-case-study';
|
||||||
export * from './lib/trial-nx-enterprise';
|
export * from './lib/trial-nx-enterprise';
|
||||||
export * from './lib/enterprise-layout';
|
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 {
|
import {
|
||||||
|
BuildingOfficeIcon,
|
||||||
GlobeAmericasIcon,
|
GlobeAmericasIcon,
|
||||||
ServerStackIcon,
|
ServerStackIcon,
|
||||||
ShieldCheckIcon,
|
ShieldCheckIcon,
|
||||||
} from '@heroicons/react/24/outline';
|
} from '@heroicons/react/24/outline';
|
||||||
import { SectionHeading } from '@nx/nx-dev/ui-common';
|
import { SectionHeading } from '@nx/nx-dev/ui-common';
|
||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
export function Security(): ReactElement {
|
export function Security(): ReactElement {
|
||||||
return (
|
return (
|
||||||
@ -99,6 +101,31 @@ export function Security(): ReactElement {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</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';
|
'use client';
|
||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { CheckCircleIcon } from '@heroicons/react/24/solid';
|
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 { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { ExclamationCircleIcon } from '@heroicons/react/24/outline';
|
||||||
|
|
||||||
export function RemoteCacheSolutions(): ReactElement {
|
export function RemoteCacheSolutions(): ReactElement {
|
||||||
return (
|
return (
|
||||||
@ -59,6 +60,24 @@ export function RemoteCacheSolutions(): ReactElement {
|
|||||||
/>
|
/>
|
||||||
<span>Free plans available, no credit card required</span>
|
<span>Free plans available, no credit card required</span>
|
||||||
</li>
|
</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">
|
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||||
<CheckCircleIcon
|
<CheckCircleIcon
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@ -75,6 +94,7 @@ export function RemoteCacheSolutions(): ReactElement {
|
|||||||
Hosted on Nx Cloud servers or on-premise with{' '}
|
Hosted on Nx Cloud servers or on-premise with{' '}
|
||||||
<Link
|
<Link
|
||||||
href="/enterprise"
|
href="/enterprise"
|
||||||
|
prefetch={false}
|
||||||
title="Learn about Nx Enterprise"
|
title="Learn about Nx Enterprise"
|
||||||
className="font-semibold underline"
|
className="font-semibold underline"
|
||||||
>
|
>
|
||||||
@ -91,13 +111,6 @@ export function RemoteCacheSolutions(): ReactElement {
|
|||||||
Enterprise grade access management and key revocation
|
Enterprise grade access management and key revocation
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</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">
|
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||||
<CheckCircleIcon
|
<CheckCircleIcon
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@ -175,6 +188,25 @@ export function RemoteCacheSolutions(): ReactElement {
|
|||||||
/>
|
/>
|
||||||
<span>Free for all users</span>
|
<span>Free for all users</span>
|
||||||
</li>
|
</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">
|
<li className="flex items-start justify-start gap-x-2 py-2.5">
|
||||||
<CheckCircleIcon
|
<CheckCircleIcon
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@ -198,23 +230,6 @@ export function RemoteCacheSolutions(): ReactElement {
|
|||||||
Simple migration path from existing 3rd party plugins
|
Simple migration path from existing 3rd party plugins
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user