Amazon Verified Permissions — Part V — Integration with AWS CloudTrail

Get familiar with Amazon Verified Permissions' auditing capabilities and integrate AVP with AWS CloudTrail.

Amazon Verified Permissions — Part V — Integration with AWS CloudTrail

This article is part of a series about Amazon Verified Permissions:

Welcome back! In this article, we will delve into the auditing capabilities of Amazon Verified Permissions. This audit trail, in computing, serves as a record of the changes made to a database or file — ensuring the security and integrity of your system. Visibility into the system’s activity is vital to security and operational best practices. The audit trail enables operational and risk auditing, governance, and compliance.

What is AWS CloudTrail?

AWS CloudTrail is an AWS service that records actions taken by a user, role, or an AWS service and records these as events. CloudTrail is active in your AWS account when you create it, and its flexibility and numerous options allow you to tailor it to your specific needs. You have a 90-day event history for free, and you can create trails to store these events in an Amazon S3 bucket, with optional delivery to Amazon CloudWatch Logs and Amazon EventBridge. The latest addition to the toolbox is AWS CloudTrail Lake, a managed data lake approach, announced on January 5th, 2022. So, you have a wealth of options to build a robust foundation for auditing, putting you firmly in control of your AWS services.

Every event contains identity information about who generated the request:

  • Root or AWS Identity and Access Management (IAM) user credentials.
  • Temporary security credentials for a role or federated user.
  • Another AWS service.

Verified Permissions API Events

CloudTrail logs all Verified Permissions API actions, also called management events. For example, calls to the CreatePolicy, DeletePolicy, or CreateIdentitySource (Cognito User Pool) actions generate entries in the CloudTrail log files. If you deployed the sample application from the previous article, head to the CloudTrail service in AWS Console and select the Event History from the left-hand side. Now filter the events based on the event source and input “verifiedpermissions.amazonaws.com”:

To access detailed information about a specific event record, click on the name in the CloudTrail service in the AWS Console. Here is an example of a PutSchema event above where I have masked some identifiable information:

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROARCVGIMMWM22HD45FP:xxxxxxxxxxxxxxxxxx",
        "arn": "arn:aws:iam::xxxxxxxxxxxx:role/aws-reserved/sso.amazonaws.com/eu-west-1/AWSReservedSSO_AWSAdministratorxxxxxxxxxxxxxx",
        "accountId": "xxxxxxxxxxxx",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE"
    },
    "eventTime": "2024-03-20T11:07:02Z",
    "eventSource": "verifiedpermissions.amazonaws.com",
    "eventName": "PutSchema",
    "awsRegion": "eu-north-1",
    "sourceIPAddress": "xx.xx.xx.xx",
    "userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.6.2 (+https://www.terraform.io) terraform-provider-aws/dev (+https://registry.terraform.io/providers/hashicorp/aws) aws-sdk-go-v2/1.25.0 os/macos lang/go#1.21.7 md/GOOS#darwin md/GOARCH#arm64 api/verifiedpermissions#1.9.0",
    "requestParameters": {
        "policyStoreId": "LYHyHqQYkP8AwggRu97Vjg"
    },
    "responseElements": {
        "policyStoreId": "LYHyHqQYkP8AwggRu97Vjg",
        "namespaces": [
            "HeroApp"
        ],
        "createdDate": "2024-03-20T11:07:02.37082Z",
        "lastUpdatedDate": "2024-03-20T11:07:02.37082Z"
    },
    "requestID": "e46be152-937f-47eb-94c4-11646fd4d7d9",
    "eventID": "ea910dbc-c624-4d6f-8110-754f253475d6",
    "readOnly": false,
    "resources": [
        {
            "accountId": "xxxxxxxxxxxx",
            "type": "AWS::VerifiedPermissions::PolicyStore",
            "ARN": "arn:aws:verifiedpermissions::xxxxxxxxxxxx:policy-store/LYHyHqQYkP8AwggRu97Vjg"
        }
    ],
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "xxxxxxxxxxxx",
    "eventCategory": "Management"
}

For example, you can continue experimenting with changing the policies and redeploying with Terraform or changing the policies in the AWS console to check how things get logged. More information about the CloudTrail record contents can be found in the AWS documentation. And more Verified Permissions examples here.

Now, we have an audit trail for the control plane, but if we also want to audit the policy engine, we need to add support for the data events.

Verified Permissions Data Events

Data events like IsAuthorized, BatchIsAuthorized, and IsAuthorizedWithToken are not logged by default. These events are interesting because you can also log the authorization decisions inside your application. To record CloudTrail data events, you must explicitly add the supported resources or resource types you want to collect activity. Data event capture requires the creation of a trail, which has additional charges.

For demonstration purposes, let’s create a new trail in the AWS Console and include only the Amazon Verified Permissions data events.

CloudTrail Setup for Data Event Logging

First, head to CloudTrail service and select the Trails menu from the left-hand side. Then push the “Create trail” button from the upper right corner:

A trail needs to have a name; let’s call it avp-data-events. By default, CloudTrail wants to create a new S3 bucket and encrypt it using a customer-managed KMS key. We are OK with the S3-managed encryption so we can check that off. From optional settings, enable the CloudWatch integration. Finally, input a name for the IAM role. Otherwise, the defaults are fine for our purposes, press the “Next” button.

Next, choose the events to be logged. We are only interested in data events, so check only that one. Select Amazon Verified Permissions as the data event type and log all events. Press the “Next” button.

Review the selection and press the “Create trail” button.

Testing the Data Events

Next is time to play around with the Hero API. I selected the user persona and made some requests via the AppSync Queries console.

Next, go to CloudWatch service, click Log groups under the Logs menu, and open the log group you specified in the previous section. Typically, CloudTrail delivers an event within 5 minutes of the API call, so be patient if you can’t see log streams with the last event timestamp straightaway.

Here is an example where I again masked some information like the AWS account identifiers and IP addresses:

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROARCVGIMMWM57KVRUAX:hero-appsync-auth-dev",
        "arn": "arn:aws:iam::xxxxxxxxxxxx:role/hero-appsync-auth-dev",
        "accountId": "xxxxxxxxxxxx",
        "accessKeyId": "ASIARCVGIMMWD6AJ54LQ"
    },
    "eventTime": "2024-03-22T10:54:07Z",
    "eventSource": "verifiedpermissions.amazonaws.com",
    "eventName": "BatchIsAuthorized",
    "awsRegion": "eu-north-1",
    "sourceIPAddress": "xx.xx.xx.xx",
    "userAgent": "aws-sdk-js/3.525.0 ua/2.0 os/linux#5.10.210-220.852.amzn2.x86_64 lang/js md/nodejs#20.11.1 api/verifiedpermissions#3.525.0 exec-env/AWS_Lambda_nodejs20.x",
    "requestParameters": {
        "requests": [
            {
                "action": {
                    "actionType": "HeroApp::Action",
                    "actionId": "AddHero"
                },
                "principal": {
                    "entityType": "HeroApp::User",
                    "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                }
            },
            {
                "action": {
                    "actionType": "HeroApp::Action",
                    "actionId": "GetHero"
                },
                "principal": {
                    "entityType": "HeroApp::User",
                    "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                }
            },
            {
                "action": {
                    "actionType": "HeroApp::Action",
                    "actionId": "ListHeroes"
                },
                "principal": {
                    "entityType": "HeroApp::User",
                    "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                }
            },
            {
                "action": {
                    "actionType": "HeroApp::Action",
                    "actionId": "GetHeroName"
                },
                "principal": {
                    "entityType": "HeroApp::User",
                    "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                }
            }
        ],
        "policyStoreId": "LYHyHqQYkP8AwggRu97Vjg"
    },
    "responseElements": null,
    "additionalEventData": {
        "results": [
            {
                "request": {
                    "principal": {
                        "entityType": "HeroApp::User",
                        "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                    },
                    "action": {
                        "actionType": "HeroApp::Action",
                        "actionId": "AddHero"
                    }
                },
                "decision": "DENY"
            },
            {
                "request": {
                    "principal": {
                        "entityType": "HeroApp::User",
                        "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                    },
                    "action": {
                        "actionType": "HeroApp::Action",
                        "actionId": "GetHero"
                    }
                },
                "decision": "ALLOW"
            },
            {
                "request": {
                    "principal": {
                        "entityType": "HeroApp::User",
                        "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                    },
                    "action": {
                        "actionType": "HeroApp::Action",
                        "actionId": "ListHeroes"
                    }
                },
                "decision": "ALLOW"
            },
            {
                "request": {
                    "principal": {
                        "entityType": "HeroApp::User",
                        "entityId": "eu-north-1_cFkdRqDX0|e8bd9731-972f-43d5-af9a-8847094a2b19"
                    },
                    "action": {
                        "actionType": "HeroApp::Action",
                        "actionId": "GetHeroName"
                    }
                },
                "decision": "DENY"
            }
        ]
    },
    "requestID": "a0ad7ed6-d68b-4c42-8a94-37c68f5f98b9",
    "eventID": "9ea01479-fc61-46bb-b1e5-71dfc97c6ad0",
    "readOnly": true,
    "resources": [
        {
            "accountId": "xxxxxxxxxxxx",
            "type": "AWS::VerifiedPermissions::PolicyStore",
            "ARN": "arn:aws:verifiedpermissions::xxxxxxxxxxxx:policy-store/LYHyHqQYkP8AwggRu97Vjg"
        }
    ],
    "eventType": "AwsApiCall",
    "managementEvent": false,
    "recipientAccountId": "xxxxxxxxxxxx",
    "eventCategory": "Data"
}

Note the difference: the managementEvent is false this time, and the eventCategory is data.

Conclusion

Integration of Amazon Verified Permissions and AWS CloudTrail increases the observability and auditability of your application. You can track which users accessed specific resources by correlating CloudTrail event records with Amazon Verified Permissions policies. This aids with security and compliance auditing. This was the first part of this series, at least for now.

Thank you for following along!

Categories:

Want to be the hero of cloud?

Great, we are here to help you become a cloud services hero!

Let's start!
Book a meeting!