diff --git a/README.md b/README.md index 4ad08007..d1efec61 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,12 @@ Errors are highlighted, so you can quickly spot suspicious behavior or bugs in y Take the investigation further with quick links into to your CloudTrail event history. +![Defend](design/readme/defend.png) + +Generate or manually configure service control policies for your accounts to help you enforce least privilege access and meet compliance requirements. + +Preview service control policies and apply them with the click of a button. + ## Open Source or SaaS Cloud Snitch is open sourced under the MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) so if you're feeling adventurous, you can deploy it directly to your own cloud. Alternatively, you can get up and running in under 5 minutes with an individual or team plan at [cloudsnitch.io](https://cloudsnitch.io). diff --git a/design/assets/gallery.pxd b/design/assets/gallery.pxd index e476503f..4e3ffacb 100644 Binary files a/design/assets/gallery.pxd and b/design/assets/gallery.pxd differ diff --git a/design/readme/defend.png b/design/readme/defend.png new file mode 100644 index 00000000..996f3e12 Binary files /dev/null and b/design/readme/defend.png differ diff --git a/design/screenshots/defend.png b/design/screenshots/defend.png new file mode 100644 index 00000000..a622266b Binary files /dev/null and b/design/screenshots/defend.png differ diff --git a/frontend/public/images/defend.png b/frontend/public/images/defend.png new file mode 100644 index 00000000..2b2ec32c Binary files /dev/null and b/frontend/public/images/defend.png differ diff --git a/frontend/src/app/(public-area)/features/page.tsx b/frontend/src/app/(public-area)/features/page.tsx index f3ae5be0..93a24e75 100644 --- a/frontend/src/app/(public-area)/features/page.tsx +++ b/frontend/src/app/(public-area)/features/page.tsx @@ -11,7 +11,7 @@ export const metadata: Metadata = { const Page = () => { return (
-
+

Explore Activity 🗺️ @@ -35,7 +35,7 @@ const Page = () => { />

-
+

Collaborate With Teammates 🤝 @@ -54,7 +54,7 @@ const Page = () => { />

-
+

Expose Bugs and Suspicious Behavior 👾 @@ -76,6 +76,27 @@ const Page = () => { />

+
+
+

+ Defend in Depth 🛡️ +

+

+ Generate or manually configure service control policies for your accounts to help you enforce + least privilege access and meet compliance requirements. +

+

Preview service control policies and apply them with the click of a button.

+
+
+ Expose Bugs and Suspicious Behavior +
+

Want more?

diff --git a/frontend/src/app/(public-area)/page.tsx b/frontend/src/app/(public-area)/page.tsx index 4ecb2c4f..91eefdd5 100644 --- a/frontend/src/app/(public-area)/page.tsx +++ b/frontend/src/app/(public-area)/page.tsx @@ -31,7 +31,10 @@ const Page = () => { to the next level.

- Cloud Snitch provides a sleek and intuitive way of exploring your AWS account activity. + Cloud Snitch provides a sleek and intuitive way of exploring your AWS account activity + along with controls to help you adopt best practices and meet compliance needs. +

+

It's a great addition to any toolbox, regardless of if you're a hobbyist that's just getting started with the cloud or a large enterprise with complex and mature cloud infrastructure. @@ -55,8 +58,8 @@ const Page = () => {

- Cloud Snitch aims to do just one thing well: Enlighten you as to what's happening in your - cloud. + Cloud Snitch aims to do just one thing well: Make sure nothing happens in your cloud without + your knowledge.

Check out our features to learn how we do it.

diff --git a/frontend/src/app/(user-area)/teams/[teamId]/Rules.tsx b/frontend/src/app/(user-area)/teams/[teamId]/Rules.tsx index 790632b8..9a6fadf9 100644 --- a/frontend/src/app/(user-area)/teams/[teamId]/Rules.tsx +++ b/frontend/src/app/(user-area)/teams/[teamId]/Rules.tsx @@ -5,7 +5,7 @@ import Link from 'next/link'; import { Transition } from '@headlessui/react'; import { awsServices } from '@/aws'; -import { Button, ChipEditor, Dialog, ErrorMessage, SuccessMessage, SyntaxHighlighter } from '@/components'; +import { Button, ChipEditor, Dialog, ErrorMessage, InfoMessage, SuccessMessage, SyntaxHighlighter } from '@/components'; import { AWSAccount } from '@/generated/api'; import { useAwsRegions, useCurrentTeamId, useManagedAwsScp, useTeamAwsAccountsMap } from '@/hooks'; import { RuleSet } from '@/rules'; @@ -72,9 +72,13 @@ interface AccountPageProps { onBack: () => void; } +interface Message { + type: 'error' | 'info' | 'success'; + message: string; +} + const AccountPage = ({ account, onBack }: AccountPageProps) => { - const [errorMessage, setErrorMessage] = useState(''); - const [successMessage, setSuccessMessage] = useState(''); + const [message, setMessage] = useState(null); const [isLoadingSuggestions, setIsLoadingSuggestions] = useState(false); const [isPreviewing, setIsPreviewing] = useState(false); const dispatch = useDispatch(); @@ -108,8 +112,7 @@ const AccountPage = ({ account, onBack }: AccountPageProps) => { return; } setIsLoadingSuggestions(true); - setErrorMessage(''); - setSuccessMessage(''); + setMessage(null); try { const [reports, awsAccessReport] = await Promise.all([ @@ -138,26 +141,29 @@ const AccountPage = ({ account, onBack }: AccountPageProps) => { } setRuleSet(ruleSet); - setSuccessMessage( - 'Based on your recent account activity, we recommend the following rules. Please review them carefully and add or remove items as needed.', + setMessage( + scpRuleSet && ruleSet.equal(scpRuleSet) + ? { + type: 'success', + message: 'Your rules are already up to date.', + } + : { + type: 'info', + message: + 'Based on your recent account activity, the following rules are recommended. Please review them carefully and add or remove items as needed.', + }, ); } catch (err) { - setErrorMessage(err instanceof Error ? err.message : 'An unknown error occurred.'); + setMessage({ + type: 'error', + message: err instanceof Error ? err.message : 'An unknown error occurred.', + }); } finally { setIsLoadingSuggestions(false); } }; impl(); - }, [ - isLoadingSuggestions, - setIsLoadingSuggestions, - dispatch, - teamId, - account, - setErrorMessage, - setSuccessMessage, - setRuleSet, - ]); + }, [isLoadingSuggestions, setIsLoadingSuggestions, dispatch, teamId, account, setMessage, setRuleSet, scpRuleSet]); return (
@@ -179,8 +185,9 @@ const AccountPage = ({ account, onBack }: AccountPageProps) => {
- {errorMessage && {errorMessage}} - {successMessage && {successMessage}} + {message?.type === 'error' && {message.message}} + {message?.type === 'info' && {message.message}} + {message?.type === 'success' && {message.message}}
@@ -253,7 +260,17 @@ const AccountPage = ({ account, onBack }: AccountPageProps) => {
setIsPreviewing(false)} title="Policy Preview"> - setIsPreviewing(false)} /> + { + setMessage({ + type: 'success', + message: 'Policy applied successfully.', + }); + setIsPreviewing(false); + }} + />