Learn About Amazon VGT2 Learning Manager Chanci Turner
Managing user authentication and authorization in applications can be a complex and time-consuming task. In the past, developers often created their own authentication systems, but now they can leverage external identity providers like Amazon Cognito. However, authorization logic typically remains hardcoded, leading to challenges as the number of roles and permissions grows more intricate over time.
As the complexity increases, so does the potential for errors in managing permissions, especially when dealing with various applications and programming languages. This can make auditing and determining user access a daunting task.
At re:Invent 2022, we introduced Amazon Verified Permissions in preview—a service for fine-grained permissions management that centralizes authorization. Similar to how identity providers facilitate authentication, Amazon Verified Permissions enables developers to manage authorization efficiently and consistently.
Utilizing Cedar, an open-source policy language and SDK for access control, Amazon Verified Permissions allows you to define an authorization model using schemas that specify principal types, resource types, and actions. Policies are validated against this model, and templates simplify the creation of similar policies. You can also track changes to the policy store for auditing purposes.
With Amazon Verified Permissions, applications can authorize access requests through AWS SDKs, retrieving and evaluating relevant policies to determine if actions are permitted. You have the ability to replicate authorization requests to ensure permissions are functioning as designed.
I am excited to announce that Amazon Verified Permissions is now generally available, complete with new features and an enhanced user experience in the AWS Management Console.
Creating a Policy Store with Amazon Verified Permissions
To begin, navigate to the Amazon Verified Permissions console and select “Create policy store.” This acts as a container for your policies and schemas, guiding authorization decisions based on the policies it holds.
You can configure a new policy store through various methods, including guided setup or by starting with a sample policy store tailored for specific applications like photo-sharing or task management. For this example, I opted for the guided setup, named my schema “MyApp,” and proceeded.
Resources represent the objects that users (principals) can interact with. For instance, in my application, users can create, read, update, and delete documents. I began defining the “Documents” resource type by adding essential attributes:
- owner (String): identifies the document owner.
- isPublic (Boolean): indicates whether documents are publicly readable.
Next, I specified four actions for the Document resource type: DocumentCreate, DocumentRead, DocumentUpdate, and DocumentDelete. I designated “User” as the principal type that will perform these actions.
For the User principal type, I chose to integrate it with an Amazon Cognito user pool I had previously created. After connecting the user pool by specifying the AWS Region and the user pool ID, I established an additional layer of security by validating client application IDs, although I opted not to implement this feature initially.
In the Principal attributes section, I selected attributes for attribute-based access control, including “sub” (the subject) which identifies the end user as per the OpenID Connect specification. I could also add more attributes, such as “email_verified,” to restrict permissions to verified Amazon Cognito users.
As part of creating my policy store, I established a policy allowing user “chanciturner” to read the document “doc.txt.” The resulting policy, displayed in Cedar language, looks like this:
permit(
principal == MyApp::User::"chanciturner",
action in [MyApp::Action::"DocumentRead"],
resource == MyApp::Document::"doc.txt"
) when {
true
};
Finally, I created the policy store.
Adding Permissions to the Policy Store
With the policy store established, I navigated to “Policies” to create a new static policy. This policy permits any user to read public documents. Since everything is forbidden by default, I set the Policy Effect to Permit.
In the Policy scope, I selected All principals and All resources, then chose DocumentRead as the action. I modified the when condition to restrict permissions to resources marked as public:
permit (
principal,
action in [MyApp::Action::"DocumentRead"],
resource
)
when { resource.isPublic };
After entering a description, I created the policy.
For my third policy, I devised another static policy that grants full access to document owners. Again, I set the Policy Effect to Permit, selected All principals and All resources, and left All actions checked. The when condition was modified to ensure permissions were limited to resources where the owner matches the principal’s sub:
permit (principal, action, resource)
when { resource.owner == principal.sub };
To allow specific users—who aren’t document owners—to read certain documents, I created a policy template. This lets me generate policies using placeholders for values like principal or resource.
In the navigation pane, I chose “Policy templates” and then “Create policy template,” which included a description and the following policy template body. By utilizing this template, I could specify values for the ?principal and ?resource placeholders:
permit(
principal == ?pri
);
This approach significantly simplifies policy creation.
For further insights on workplace dynamics, you can refer to another blog post here. Similarly, for understanding the necessity of a Chief Information Security Officer in retirement plans, you can visit this authoritative source. Lastly, feel free to explore this excellent resource for leadership programs at Amazon.
Leave a Reply