Amazon EKS audit logs are available through CloudWatch Logs. Use the k8saudit-eks Falco plugin.
Before you begin
-
Falco built with
k8saudit-eksandjsonplugins. -
EKS cluster with control plane logging enabled.
Procedure
- Enable control plane logging in the AWS Console.
- Navigate to your EKS cluster.
- Go to .
- Enable Audit logging.
- Configure IAM permissions for EC2 node groups in the AWS Console.

Note
This step applies to EKS clusters using EC2-backed node groups. If your cluster uses Fargate, skip to the next step.- Navigate to , and then click the node group name.
- Click Node IAM role ARN to open IAM.
- Add the following inline policy:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadAccessToCloudWatchLogs", "Effect": "Allow", "Action": [ "logs:Describe*", "logs:FilterLogEvents", "logs:Get*", "logs:List*" ], "Resource": [ "arn:aws:logs:${region}:${account-id}:log-group:/aws/eks/${cluster-name}/cluster:*" ] } ] }Replace${region},${account-id}, and${cluster-name}with your values. - Configure IRSA for Fargate.

Note
This step applies to EKS clusters using Fargate. If your cluster uses EC2-backed node groups, skip to the next step.Fargate blocks access to the EC2 Instance Metadata Service (IMDS), so pods cannot inherit IAM roles from the Fargate execution role. IRSA (IAM Roles for Service Accounts) is the only way to provide AWS credentials to containers on Fargate.- Get the EKS OIDC provider ID.
OIDC_ID=$(aws eks describe-cluster --name <CLUSTER_NAME> \ --query "cluster.identity.oidc.issuer" --output text | sed 's|.*/id/||')
- Create an IAM role with a trust policy.Replace the following variables with your values:
-
<ACCOUNT_ID>: AWS account ID. -
<OIDC_ID>: From step 3a above. -
<REGION>: For example,us-east-1. -
<NAMESPACE>. For example,trendmicro-system). -
<SA_NAME>: The default isaudit-log-collector-trendmicro-container-security).
cat > trust-policy.json << EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>:sub": "system:serviceaccount:<NAMESPACE>:<SA_NAME>", "oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>:aud": "sts.amazonaws.com" } } } ] } EOF aws iam create-role \ --role-name audit-log-collector-irsa \ --assume-role-policy-document file://trust-policy.json -
- Attach the CloudWatch Logs read policy to the role.
aws iam put-role-policy \ --role-name audit-log-collector-irsa \ --policy-name audit-log-cloudwatch-read \ --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadAccessToCloudWatchLogs", "Effect": "Allow", "Action": [ "logs:Describe*", "logs:FilterLogEvents", "logs:Get*", "logs:List*" ], "Resource": [ "arn:aws:logs:<REGION>:<ACCOUNT_ID>:log-group:/aws/eks/<CLUSTER_NAME>/cluster:*" ] } ] }'
- Get the EKS OIDC provider ID.
- Update the
overrides.yamlto enable audit log collection.For EC2 node groups:visionOne: bootstrapToken: ... endpoint: ... exclusion: namespaces: [kube-system] ... auditLogCollection: enabled: true provider: eks eks: region: "${your cluster's region}" clusterName: "${your cluster's name in aws console}"For Fargate, add the IRSA annotation for the service account:visionOne: bootstrapToken: ... endpoint: ... exclusion: namespaces: [kube-system] ... auditLogCollection: enabled: true provider: eks eks: region: "${your cluster's region}" clusterName: "${your cluster's name in aws console}" serviceAccount: auditLogCollector: annotations: eks.amazonaws.com/role-arn: "arn:aws:iam::<ACCOUNT_ID>:role/audit-log-collector-irsa"
Troubleshooting: NoCredentialProviders Error (EC2 Node Groups Only)
If you see
Error: NoCredentialProviders: no valid providers in
chain:Cause: Container cannot reach IMDS because of a hop limit.
Solution:
# Get instance ID INSTANCE_ID=$(aws ec2 describe-instances --region <region> \ --filters "Name=private-dns-name,Values=<node-name>" \ --query "Reservations[0].Instances[0].InstanceId" --output text) # Increase hop limit aws ec2 modify-instance-metadata-options --region <region> \ --instance-id $INSTANCE_ID \ --http-put-response-hop-limit 2 # Restart pod kubectl delete pod -n trendmicro-system <pod-name>
Fargate Verification
# Check pod is running
kubectl get pods -n trendmicro-system -l app.kubernetes.io/component=trendmicro-audit-log-collector
# Check IRSA env vars are injected
kubectl get pod <POD_NAME> -n trendmicro-system -o jsonpath='{.spec.containers[0].env[?(@.name=="AWS_ROLE_ARN")].value}'
# Check logs for successful event upload
kubectl logs -n trendmicro-system -l app.kubernetes.io/component=trendmicro-audit-log-collector -c audit-log-collector --tail=10
Expected healthy log
output:
{"level":"info","logger":"event-uploader","msg":"Batch upload completed","success":1,"failed":0}
