diff --git a/docs/features/aws-iam/tutorials/aws-visibility.mdx b/docs/features/aws-iam/tutorials/aws-visibility.mdx index 7a252f0fd..e642f72e1 100644 --- a/docs/features/aws-iam/tutorials/aws-visibility.mdx +++ b/docs/features/aws-iam/tutorials/aws-visibility.mdx @@ -4,29 +4,29 @@ title: AWS resource mapping & IAM policy generation image: /img/quick-tutorials/aws-iam-visibility/social.png --- +Many production Kubernetes workloads depend on cloud resources, such as S3 buckets, RDS databases, and Lambda functions. In this tutorial, you will learn how Otterize can enhance your visibility into the AWS resources that are accessed by your workloads. -Many production Kubernetes workloads rely on cloud resources, like S3 Buckets, RDS databases, and Lambda functions. In this tutorial, we will look at how Otterize provides visibility into the AWS resources called by your workloads. +In this tutorial, you will: -In this tutorial, we will: * Set up an EKS cluster. * Deploy two Lambda functions. -* Deploy a server pod that retrieves a joke (as in, a string containing a joke ;) from a Lambda, provides a review, and posts the review to another Lambda. -* Automatically detect and view the Lambda function calls in Otterize. +* Deploy a *server* pod that retrieves a joke (as a string) from one Lambda function, reviews it, and posts the review to another Lambda function. +* Automatically detect and monitor the Lambda function calls using Otterize. -By the end, you'll know how to map Kubernetes workloads alongside their dependent AWS resources using Otterize. +By the end of this tutorial, you will understand how to map Kubernetes workloads and their associated AWS resources using Otterize. ## Prerequisites ### CLI tools -We will need the following CLI tools to set up our cluster and deploy our scripts. +You will need the following CLI tools to work with this environment: -1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). You will also need credentials within the target account with permissions to work with EKS clusters, IAM, CloudFormation, and Lambda functions. -2. [eksctl](https://eksctl.io/installation/) +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) - Ensure you have credentials within the target account that grant permissions to work with EKS clusters, IAM, CloudFormation, and Lambda functions. +2. [eksctl](https://eksctl.io/installation/) - This tool simplifies the creation and management of an EKS cluster. ### Create an EKS cluster -Already have Otterize deployed with the IAM integration configured on your cluster? [Skip to the tutorial.](#tutorial) +Already have EKS cluster? Skip to the [next step](#enable-aws-visibility-with-otterize-installation). -Begin by creating an EKS cluster for pod deployment using **eksctl** with the YAML configuration below: +Start by creating an EKS cluster for deploying your pods. Use the **eksctl** tool with the following YAML configuration: ```bash curl ${ABSOLUTE_URL}/code-examples/aws-visibility/eks-cluster.yaml | eksctl create cluster -f - ``` @@ -38,25 +38,17 @@ curl ${ABSOLUTE_URL}/code-examples/aws-visibility/eks-cluster.yaml | eksctl crea ``` -Next, update **kubeconfig** to link it with the new cluster: +Next, update your **kubeconfig** to connect with the new cluster. ```bash aws eks update-kubeconfig --name otterize-tutorial-aws-visibility --region 'us-west-2' ``` -### Enable AWS Visibility with Otterize Installation -To provide visibility, we will need to install Otterize in our cluster, and we will want to enable AWS IAM roles for service accounts (IRSA) on our cluster. We can quickly enable this using a cloudformation template on the Otterize Cloud Integrations page. +### Enable AWS Visibility +You will first need to install Otterize in your cluster. If your cluster is not already connected, you can do so by following the Kubernetes setup instructions detailed on the [Integrations](https://app.otterize.com/integrations) page. -1. **Install Otterize** -If you don't have a connected Kubernetes cluster, create one via [Integrations page](https://app.otterize.com/integrations) and follow the setup instructions for Kubernetes. Skip if your cluster is already connected. - -2. **Integrate AWS with Otterize Cloud** -To begin the integration with AWS, visit the [Integrations page](https://app.otterize.com/integrations). Once there, you will be asked for information to help populate a CloudFormation template we will use to set up roles and policies for the Otterize deployment in our cluster. - -If you created the EKS cluster above, the cluster name would be `otterize-tutorial-aws-visibility`, and the region would be `us-west-2`. - -Once the information is provided, a *Launch Cloudformation* button will take you to the AWS Console to deploy the cloudformation script. This script will install IRSA within your EKS cluster and enable Otterize Cloud to manage intents. - -After IRSA is enabled in your cluster, you need to redeploy Otterize with the AWS credential operator and AWS visibility enabled. In Otterize Cloud, click the *Next* button to see the updated Helm commands. AWS Visibility is not enabled by default. Before executing the revised configuration, you will need to set an additional flag at the end of the command: +:::info Important +When installing Otterize, append the following flag to the helm command to enable aws visibility: +::: ```bash --set networkMapper.aws.visibility.enabled=true @@ -64,13 +56,14 @@ After IRSA is enabled in your cluster, you need to redeploy Otterize with the AW ## Tutorial -Having configured our environment, we'll deploy AWS resources, authorize pod access using ClientIntents, and monitor access in Otterize Cloud. +Now that your environment is set up, you are ready to deploy the application components, including the AWS resources that Otterize will monitor. ### Deploy two Lambda functions -First, we will deploy two Lambda functions (`DadJokeLambdaFunction` and `FeedbackLambdaFunction`). These services will work alongside our server pod to generate a humor training dataset. This works by receiving a joke from the DadJokeLambdaFunction, the server pod reviewing the joke, and then sending the feedback to the FeedbackLambdaFunction. +First, you will deploy two Lambda functions: `DadJokeLambdaFunction` and `FeedbackLambdaFunction`. These functions will interact with your *server* pod to generate a dad joke training dataset. The *server* pod receives a joke from the ``DadJokeLambdaFunction``, reviews the joke, and sends the feedback to the `FeedbackLambdaFunction`. + +To deploy the Lambda functions and their required roles, use the following command: -We can deploy the lambda functions and their required roles with the following command: ```bash curl ${ABSOLUTE_URL}/code-examples/aws-visibility/cloudformation.yaml -o template.yaml && \ aws cloudformation deploy --template-file template.yaml --stack-name OtterizeTutorialJokeTrainingStack --capabilities CAPABILITY_IAM --region 'us-west-2' @@ -85,22 +78,44 @@ aws cloudformation deploy --template-file template.yaml --stack-name OtterizeTut ### Deploy server with access to Lambda functions -Now that our Lambdas are deployed, we want to deploy our server pod within our cluster and point it to our two Lambda functions. In the commands below, we will create a configmap to hold our functions ARNs and pass the map into our deployment YAML. +With the Lambda functions deployed, you're now ready to deploy your *server* pod and configure it to interact with the two Lambda functions. Follow these steps to set up your environment: -```bash +- Create a namespace: +```bash kubectl create namespace otterize-tutorial-aws-visibility +``` + +- Retrieve Lambda ARNs: +```bash DAD_JOKE_LAMBDA_ARN=$(aws cloudformation describe-stacks --region 'us-west-2' --stack-name OtterizeTutorialJokeTrainingStack --query "Stacks[0].Outputs[?OutputKey=='DadJokeLambdaFunction'].OutputValue" --output text) FEEDBACK_LAMBDA_ARN=$(aws cloudformation describe-stacks --region 'us-west-2' --stack-name OtterizeTutorialJokeTrainingStack --query "Stacks[0].Outputs[?OutputKey=='FeedbackLambdaFunction'].OutputValue" --output text) +``` + +- Create a `ConfigMap` for Lambda ARNs: +```bash kubectl create configmap lambda-arns \ --from-literal=dadJokeLambdaArn=$DAD_JOKE_LAMBDA_ARN \ --from-literal=feedbackLambdaArn=$FEEDBACK_LAMBDA_ARN \ -n otterize-tutorial-aws-visibility +``` + +- Generate AWS credentials and create a `Secret`: +```bash +USER_NAME=$(aws cloudformation describe-stacks --region 'us-west-2' --stack-name OtterizeTutorialJokeTrainingStack --query "Stacks[0].Outputs[?OutputKey=='LambdaInvokeUserAccessKeyId'].OutputValue" --output text) + +aws iam create-access-key --user-name "$USER_NAME" | \ +jq -r '"--from-literal=AWS_ACCESS_KEY_ID="+.AccessKey.AccessKeyId+" --from-literal=AWS_SECRET_ACCESS_KEY="+.AccessKey.SecretAccessKey' | \ +xargs kubectl create secret generic aws-credentials -n otterize-tutorial-aws-visibility +``` +- Deploy the *server* pod: +```bash kubectl apply -n otterize-tutorial-aws-visibility -f ${ABSOLUTE_URL}/code-examples/aws-visibility/all.yaml ``` +
Inspect deployment YAML @@ -109,36 +124,14 @@ kubectl apply -n otterize-tutorial-aws-visibility -f ${ABSOLUTE_URL}/code-exampl ```
-Inspecting our deployment YAML, you will see we have added two labels to our pod. The first `network-mapper.otterize.com/aws-visibility` informs the network mapper to identify AWS API calls, and the `credentials-operator.otterize.com/create-aws-role` that drives the credentials operator to create a role specifically for this pod that will be used for our intents. +In the Kubernetes `Deployment` manifest, you will notice the following label in the pod template: `network-mapper.otterize.com/aws-visibility`. This label instructs the network mapper to track AWS API calls for this pod, helping identify the resources and actions being utilized. -Once our pod is deployed, we can inspect the logs and see that we cannot access the Lambda functions. +Once the pod is deployed, you can verify the logs to confirm it is successfully calling the Lambda functions: ```bash kubectl logs -f -n otterize-tutorial-aws-visibility deploy/joketrainer ``` -Sample output: -``` -invoke error, operation error Lambda: Invoke, https response error StatusCode: 403, RequestID: a3bab063-dfb0-49e3-b466-0069807c56fa, api error AccessDeniedException: User: arn:aws:sts::12345678910:assumed-role/otr-otterize-tutorial-aws-visibility.default@otterize-tut-ecfd9d/12345678910 is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-west-2:12345678910:function:OtterizeTutorialJokeTrainingStack-DadJokeLambda-dnNYqlwipYxG because no identity-based policy allows the lambda:InvokeFunction action -``` - -### Applying Intents - -We can apply an intent for our pod to be able to call the Lambda functions created by our cloudformation stack. - -```bash -kubectl apply -n otterize-tutorial-aws-visibility -f ${ABSOLUTE_URL}/code-examples/aws-visibility/intents.yaml -``` - -```yaml -{@include: ../../../../static/code-examples/aws-visibility/intents.yaml} -``` - -We can now recheck the logs to ensure that the pod is running: -```bash -kubectl logs -f -n otterize-tutorial-aws-visibility deploy/joketrainer -``` - Example output: ``` Joke: People saying 'boo! to their friends has risen by 85% in the last year.... That's a frightening statistic. @@ -151,16 +144,14 @@ Sending Feedback of Funny?: No ``` ### Visualize Relationships -The Otterize network mapper inspects pods with the `network-mapper.otterize.com/aws-visibility: true` label. For the labeled pods, the network mapper will identify AWS API calls made by that pod and determine which resources and actions are being used. This information is shown on the [Access graph](https://app.otterize.com/access-graph). -In the Access graph screenshot below, you’ll see 4 AWS resources associated with our *joketrainer* pod: *DadJokeLambdaFunction*, *FeedbackLambdaFunction*, the role assumed by our server pod, and our wildcard intent definition. This wildcard definition matches any Lambdas created by our cloudformation stack. These types of wildcard definitions can be helpful for AWS Resources with dynamic ARN names as you move across staging and production deployments. Still, they open up a security space that could be overly permissive for some environments. Otterize makes deploying with a wildcard definition easy and then applying more stringent authorization without disrupting any services. +With Otterize monitoring the AWS API calls, access Otterize Cloud to observe both Lambdas in action. The [Access graph](https://app.otterize.com/access-graph) will display two AWS resources associated with the *joketrainer* pod: *DadJokeLambdaFunction* and *FeedbackLambdaFunction*. ![Otterize Cloud AWS Visibility Example](/img/quick-tutorials/aws-iam-visibility/aws-iam-visibility.png) - ### What's Next -Now that we've discovered the AWS resources used within a Kubernetes workload, you can learn more about how you can manage access to these resources with Otterize in the [Automate AWS IAM for EKS](/features/aws-iam/tutorials/aws-iam-eks) tutorial. +Now that you have learned how to enable visibility for AWS resources in your Kubernetes cluster, you are ready to explore how to manage access to these resources. Continue your learning journey with the next tutorial: [Automate AWS IAM for EKS](/features/aws-iam/tutorials/aws-iam-eks). ## Cleanup @@ -171,7 +162,7 @@ kubectl delete namespace otterize-tutorial-aws-visibility To remove the Lambda functions: ```bash -aws cloudformation delete-stack --stack-name OtterizeTutorialJokeTrainingStack +aws cloudformation delete-stack --stack-name OtterizeTutorialJokeTrainingStack --region 'us-west-2' ``` To remove the EKS cluster: diff --git a/static/code-examples/aws-visibility/all.yaml b/static/code-examples/aws-visibility/all.yaml index 14c78b2bc..19028bf99 100644 --- a/static/code-examples/aws-visibility/all.yaml +++ b/static/code-examples/aws-visibility/all.yaml @@ -13,12 +13,21 @@ spec: labels: app: joketrainer network-mapper.otterize.com/aws-visibility: "true" - credentials-operator.otterize.com/create-aws-role: "true" spec: containers: - name: joketrainer image: otterize/aws-visibility-tutorial:latest env: + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: aws-credentials + key: AWS_ACCESS_KEY_ID + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: aws-credentials + key: AWS_SECRET_ACCESS_KEY - name: DAD_JOKE_LAMBDA_ARN valueFrom: configMapKeyRef: diff --git a/static/code-examples/aws-visibility/cloudformation.yaml b/static/code-examples/aws-visibility/cloudformation.yaml index ee8b20a56..2f30c10dc 100644 --- a/static/code-examples/aws-visibility/cloudformation.yaml +++ b/static/code-examples/aws-visibility/cloudformation.yaml @@ -93,6 +93,26 @@ Resources: }; Timeout: 10 + LambdaInvokeUser: + Type: 'AWS::IAM::User' + + LambdaInvokePolicy: + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: 'LambdaInvokePolicy' + Users: + - !Ref LambdaInvokeUser + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: 'lambda:InvokeFunction' + Resource: + - !GetAtt DadJokeLambda.Arn + - !GetAtt FeedbackLambda.Arn + + + Outputs: DadJokeLambdaFunction: Description: "Dad Joke Lambda Function ARN" @@ -102,3 +122,6 @@ Outputs: Description: "Feedback Lambda Function ARN" Value: !GetAtt FeedbackLambda.Arn + LambdaInvokeUserAccessKeyId: + Description: "IAM User Name for accessing Joke Lambda" + Value: !Ref LambdaInvokeUser \ No newline at end of file diff --git a/static/img/quick-tutorials/aws-iam-visibility/aws-iam-visibility.png b/static/img/quick-tutorials/aws-iam-visibility/aws-iam-visibility.png index bd627dfb7..5e230f286 100644 Binary files a/static/img/quick-tutorials/aws-iam-visibility/aws-iam-visibility.png and b/static/img/quick-tutorials/aws-iam-visibility/aws-iam-visibility.png differ