Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplified AWS Visibility Tutorial #226

Merged
merged 4 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 49 additions & 58 deletions docs/features/aws-iam/tutorials/aws-visibility.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 -
```
Expand All @@ -38,39 +38,32 @@ curl ${ABSOLUTE_URL}/code-examples/aws-visibility/eks-cluster.yaml | eksctl crea
```
</details>

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
```

## 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'
Expand All @@ -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
```

<details>
<summary>Inspect deployment YAML</summary>

Expand All @@ -109,36 +124,14 @@ kubectl apply -n otterize-tutorial-aws-visibility -f ${ABSOLUTE_URL}/code-exampl
```
</details>

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.
Expand All @@ -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

Expand All @@ -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:
Expand Down
11 changes: 10 additions & 1 deletion static/code-examples/aws-visibility/all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
23 changes: 23 additions & 0 deletions static/code-examples/aws-visibility/cloudformation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading