<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matt Adorjan</title>
    <description>The latest articles on DEV Community by Matt Adorjan (@mda590).</description>
    <link>https://dev.to/mda590</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F60556%2Faa2e8da6-0857-4899-8701-b552f55901fb.jpeg</url>
      <title>DEV Community: Matt Adorjan</title>
      <link>https://dev.to/mda590</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mda590"/>
    <language>en</language>
    <item>
      <title>Enhancing Cloud Resilience: Unveiling Amazon Application Recovery Controller’s Latest Features for Seamless Application Recovery</title>
      <dc:creator>Matt Adorjan</dc:creator>
      <pubDate>Mon, 25 Nov 2024 18:33:23 +0000</pubDate>
      <link>https://dev.to/mda590/enhancing-cloud-resilience-unveiling-amazon-application-recovery-controllers-latest-features-for-4702</link>
      <guid>https://dev.to/mda590/enhancing-cloud-resilience-unveiling-amazon-application-recovery-controllers-latest-features-for-4702</guid>
      <description>&lt;p&gt;Amazon Application Recovery Controller (ARC) is an AWS service designed to help organizations prepare for and execute faster recovery of applications running on AWS’s global cloud infrastructure. ARC provides insights into whether applications and resources are ready for recovery and helps manage and coordinate recovery across AWS Regions and Availability Zones (AZs). This capability reduces the manual steps traditionally required for application recovery, making it simpler and more reliable. It can also help put control of application failovers and fail backs into the hands of your developers, minimizing dependence on your infrastructure teams. In this post, I want to summarize some of the key benefits, recent announcements, and why these are important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-Availability Zone (AZ) Recovery: ARC offers zonal shift and zonal autoshift capabilities to recover from single AZ impairments by redirecting traffic from an impaired AZ to a healthy one.&lt;/li&gt;
&lt;li&gt;Multi-Region Recovery: This includes routing control for failover and readiness checks to monitor application readiness, ensuring applications are configured to handle failover traffic.&lt;/li&gt;
&lt;li&gt;Routing Control: Allows rerouting of application traffic across different AWS Regions or AZs using simple on/off switches integrated with Amazon Route 53 health checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example Walkthrough: Using ARC
&lt;/h2&gt;

&lt;p&gt;To demonstrate how to use ARC, consider setting up a multi-Region recovery strategy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prepare Your Applications: Ensure your applications are set up as siloed replicas in multiple AWS Regions. This setup allows traffic failover from a primary application to a secondary one during an event.&lt;/li&gt;
&lt;li&gt;Create Routing Controls:

&lt;ul&gt;
&lt;li&gt;Establish routing controls in ARC to manage traffic flow between Regions.&lt;/li&gt;
&lt;li&gt;Use the Amazon Route 53 data plane for DNS-based failover, associating each replica with a routing control.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Implement Safety Rules:

&lt;ul&gt;
&lt;li&gt;Define safety rules to prevent unintended outcomes during failover, such as ensuring only one replica is active at any time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Readiness Checks:

&lt;ul&gt;
&lt;li&gt;Continuously monitor resource quotas, capacity, and network routing policies to ensure readiness for failover.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Failover Execution:

&lt;ul&gt;
&lt;li&gt;During an event, use the ARC API or AWS CLI to update routing control states and reroute traffic, ensuring application availability across Regions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Expanding Zonal Shift Capabilities: From Load Balancers to Compute Services
&lt;/h2&gt;

&lt;p&gt;Most recently, Amazon Application Recovery Controller (ARC) has significantly expanded its zonal shift and zonal autoshift capabilities, moving beyond load balancers to encompass critical compute services. This expansion marks a crucial evolution in AWS’s approach to application resilience and recovery.&lt;/p&gt;

&lt;h3&gt;
  
  
  From Load Balancers to Compute Services
&lt;/h3&gt;

&lt;p&gt;Initially, ARC’s zonal shift functionality was limited to Application Load Balancers (ALBs) and Network Load Balancers (NLBs). While this provided valuable traffic management during AZ impairments, it didn’t address the underlying compute resources. Now, ARC has extended its support to include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;EC2 Auto Scaling Groups (ASGs): As of November 18, 2024, &lt;a href="https://aws.amazon.com/about-aws/whats-new/2024/11/ec2-auto-scaling-application-recovery-controller-zonal-shift/" rel="noopener noreferrer"&gt;EC2 Auto Scaling now supports ARC zonal shift and zonal autoshift&lt;/a&gt;. This integration allows for the rapid recovery of applications by shifting EC2 instance launches away from impaired AZs.&lt;/li&gt;
&lt;li&gt;Amazon Elastic Kubernetes Service (EKS): &lt;a href="https://aws.amazon.com/about-aws/whats-new/2024/10/amazon-eks-application-recovery-controller-arc/" rel="noopener noreferrer"&gt;Announced on November 8&lt;/a&gt;, 2024, ARC now supports zonal shift and zonal autoshift for EKS clusters. This capability helps in managing Kubernetes workloads during AZ impairments.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Importance of Compute Service Integration
&lt;/h3&gt;

&lt;p&gt;The extension of zonal shift to compute services is significant for several reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comprehensive Recovery: By including EC2 Auto Scaling and EKS, ARC now offers a more holistic approach to application recovery. It addresses not just traffic routing but also the underlying compute resources, ensuring a more robust recovery process.&lt;/li&gt;
&lt;li&gt;Automated Instance Management: For EC2 Auto Scaling, zonal shift can prevent new instance launches in impaired AZs and redirect them to healthy ones, reducing the impact of “gray failures” that might not be immediately detected by standard health checks.&lt;/li&gt;
&lt;li&gt;Kubernetes-Specific Benefits: In EKS clusters, zonal shift cordons nodes in the impacted AZ and ensures new pods are scheduled only in healthy AZs, maintaining application availability in containerized environments.&lt;/li&gt;
&lt;li&gt;Enhanced Multi-AZ Resilience: This expansion allows for more sophisticated multi-AZ resilience strategies, enabling organizations to maintain application performance and availability even during significant AZ impairments.&lt;/li&gt;
&lt;li&gt;Reduced Manual Intervention: The integration with compute services, especially with the autoshift feature, reduces the need for manual intervention during AZ failures, leading to faster recovery times and reduced operational overhead.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By extending zonal shift capabilities to these core compute services, AWS has significantly enhanced the ability of organizations to maintain application resilience and quickly recover from AZ-level failures. This evolution represents a more integrated and automated approach to application recovery in cloud environments, aligning closely with the needs of modern, highly available applications.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>disasterrecovery</category>
      <category>failover</category>
    </item>
    <item>
      <title>Building Faster Event-Driven Architectures: Exploring Amazon EventBridge’s New Latency Gains</title>
      <dc:creator>Matt Adorjan</dc:creator>
      <pubDate>Sun, 17 Nov 2024 14:53:43 +0000</pubDate>
      <link>https://dev.to/mda590/building-faster-event-driven-architectures-exploring-amazon-eventbridges-new-latency-gains-3l6</link>
      <guid>https://dev.to/mda590/building-faster-event-driven-architectures-exploring-amazon-eventbridges-new-latency-gains-3l6</guid>
      <description>&lt;p&gt;When milliseconds matter, every improvement counts. &lt;a href="https://aws.amazon.com/about-aws/whats-new/2024/11/amazon-eventbridge-improvement-latency-event-buses/" rel="noopener noreferrer"&gt;Amazon EventBridge just announced&lt;/a&gt; a staggering 94% reduction in end-to-end latency for Event Buses, now as low as 129ms at the 99th percentile. For developers and organizations building latency-sensitive, mission-critical applications, this change opens the door to even more responsive and efficient event-driven architectures.&lt;/p&gt;

&lt;p&gt;In this post, I'll explore why latency improvements like these are game-changers, demonstrate how you can test and monitor this performance, and highlight the benefits for real-world use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Latency Matters
&lt;/h2&gt;

&lt;p&gt;In event-driven systems, delays, however small, can create bottlenecks. Consider applications like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fraud detection: A delay in processing transaction data could allow fraudulent activity to slip through.&lt;/li&gt;
&lt;li&gt;Industrial automation: Late responses to sensor events might disrupt production or reduce operational efficiency.&lt;/li&gt;
&lt;li&gt;Gaming applications: High latency can ruin player experiences in real-time multiplayer environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By reducing average latency from 2235ms in January 2023 to just 129ms in August 2024 (P99), Amazon EventBridge empowers developers to react to critical events faster than ever. This improvement translates to better customer experiences, more agile business processes, and the potential for innovation in real-time systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Promise: Real-World Observations from CloudPing.co
&lt;/h2&gt;

&lt;p&gt;To validate Amazon EventBridge’s latency improvements, I turned to a real-world application: CloudPing.co, which uses EventBridge and AWS Lambda functions to handle event-driven workflows. By analyzing the IngestionToInvocationStartLatency metric from one of our backend data-collection Lambda functions, I observed a clear and dramatic improvement in latency trends starting July 31, 2024.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insights from the Data:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before July 31, 2024&lt;/strong&gt;: The latency was more variable and consistently higher, with peaks near the upper end of the range (~141ms).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After July 31, 2024&lt;/strong&gt;: There’s a noticeable and sustained drop in average latency, aligning with Amazon EventBridge’s announcement of up to a 94% reduction. The trendline shows a much lower and stable average, making event handling significantly faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Impact Observed:
&lt;/h3&gt;

&lt;p&gt;This reduction in latency directly translates into faster invocation of Lambda functions, ensuring more responsive event-driven workflows. Applications that rely on timely processing of events benefit from this improvement by delivering results more quickly and reliably to their users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualization:
&lt;/h3&gt;

&lt;p&gt;The graph below illustrates this trend clearly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydtjehrai5jmokmcpec1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydtjehrai5jmokmcpec1.png" alt="IngestionToInvocationStartLatency Average for 12 Months" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Benefits of Lower Latency
&lt;/h2&gt;

&lt;p&gt;These performance gains unlock a host of benefits for businesses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time insights and decisions: Detect and respond to events faster, enabling agility in decision-making.&lt;/li&gt;
&lt;li&gt;Seamless scaling: Handle latency-sensitive applications without re-engineering your infrastructure.&lt;/li&gt;
&lt;li&gt;Cost efficiency: Latency improvements are applied by default across all AWS regions, at no additional cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Monitor and Test Latency
&lt;/h2&gt;

&lt;p&gt;EventBridge provides built-in tools to help you measure and optimize event latency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Metrics: Use the CloudWatch metrics &lt;code&gt;IngestionToInvocationStartLatency&lt;/code&gt; and &lt;code&gt;IngestionToInvocationSuccessLatency&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Console Dashboards: Monitor latency trends directly in the EventBridge console.&lt;/li&gt;
&lt;li&gt;Real-world Scenarios: Test specific workflows like order processing, data pipelines, or gaming events to see the performance impact.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Take Advantage of EventBridge’s Performance Gains
&lt;/h2&gt;

&lt;p&gt;Whether you’re building a fraud detection system, optimizing industrial automation, or creating immersive gaming experiences, Amazon EventBridge’s latency improvements can help you achieve new levels of performance.&lt;/p&gt;

&lt;p&gt;Getting started is simple! Check out the documentation and spin up your first Event Bus in the AWS Console. By taking advantage of EventBridge’s improvements, you can ensure your applications are faster, more reliable, and ready for the demands of real-time processing.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>eventbridge</category>
      <category>streaming</category>
    </item>
    <item>
      <title>Unlocking Fine-Grained Authorization with Amazon Verified Permissions: An Underrated AWS Service</title>
      <dc:creator>Matt Adorjan</dc:creator>
      <pubDate>Mon, 11 Nov 2024 12:48:57 +0000</pubDate>
      <link>https://dev.to/mda590/unlocking-fine-grained-authorization-with-amazon-verified-permissions-an-underrated-aws-service-5bjn</link>
      <guid>https://dev.to/mda590/unlocking-fine-grained-authorization-with-amazon-verified-permissions-an-underrated-aws-service-5bjn</guid>
      <description>&lt;p&gt;In today’s application landscape, a comprehensive authorization solution is crucial for maintaining security and compliance. Amazon Verified Permissions (AVP) is an (I feel) often-overlooked service that offers powerful, fine-grained authorization capabilities for custom applications. Let’s explore this AWS service and discover how it can enhance your application’s security posture.&lt;/p&gt;

&lt;p&gt;As I have worked across different AWS implementations and application deployments, there is often a desire by developers to implement their own authorization services, write their own policy language, check permissions stored in various database technologies, and otherwise fragment the authorization process. AWS released Amazon Verified Permissions service a while ago, but I don't see it talked about very much, and for organizations which are heavily invested in AWS, I think it is a great drop in solution for permissions and authorization management.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Amazon Verified Permissions?
&lt;/h2&gt;

&lt;p&gt;Amazon Verified Permissions is a fully managed, scalable authorization service designed for custom applications. It uses the &lt;a href="https://www.cedarpolicy.com/" rel="noopener noreferrer"&gt;Cedar policy language&lt;/a&gt; to define and enforce fine-grained permissions, allowing developers to externalize authorization logic and centralize policy management.&lt;/p&gt;

&lt;p&gt;Key features of AVP include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fine-grained authorization using roles and attributes&lt;/li&gt;
&lt;li&gt;Centralized policy management&lt;/li&gt;
&lt;li&gt;Integration with identity providers like Amazon Cognito&lt;/li&gt;
&lt;li&gt;Real-time authorization decisions&lt;/li&gt;
&lt;li&gt;Automated policy analysis for compliance and auditing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Amazon Verified Permissions Works
&lt;/h2&gt;

&lt;p&gt;AVP leverages the Cedar policy language, an open-source language designed for writing and evaluating authorization policies. Here’s how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define your authorization model using Cedar policies&lt;/li&gt;
&lt;li&gt;Store and manage these policies in AVP&lt;/li&gt;
&lt;li&gt;When a user attempts an action, your application sends an authorization request to AVP&lt;/li&gt;
&lt;li&gt;AVP evaluates the request against relevant policies and returns an &lt;code&gt;ALLOW&lt;/code&gt; or &lt;code&gt;DENY&lt;/code&gt; decision&lt;/li&gt;
&lt;li&gt;Your application enforces the decision&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Key Components of AVP
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Policy Management and Validation
&lt;/h3&gt;

&lt;p&gt;AVP provides tools for creating, storing, and managing Cedar policies. It also offers policy validation to ensure that your policies are correctly formatted and align with your defined schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Policy Querying and Auditing
&lt;/h3&gt;

&lt;p&gt;The service includes features for analyzing and auditing policies, helping you identify potential security issues or overly privileged access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrations and Extensibility
&lt;/h3&gt;

&lt;p&gt;AVP can integrate with identity providers like Amazon Cognito and works alongside other AWS services to provide a comprehensive authorization solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with AVP
&lt;/h2&gt;

&lt;p&gt;Let’s walk through a basic example of using AVP with Python. First, set up your AWS credentials and install the &lt;code&gt;boto3&lt;/code&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="c1"&gt;# Create a Verified Permissions client
&lt;/span&gt;&lt;span class="n"&gt;avp_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;verifiedpermissions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define a simple policy
&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AllowViewDocument&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Effect&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Allow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Principal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Identifier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User::Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Document::View&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Resource&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Identifier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Document::ProjectReport&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Create a policy store
&lt;/span&gt;&lt;span class="n"&gt;policy_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;avp_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_policy_store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MyAppPolicyStore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a policy in the policy store
&lt;/span&gt;&lt;span class="n"&gt;created_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;avp_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;policyStoreId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy_store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;policyStoreId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check authorization
&lt;/span&gt;&lt;span class="n"&gt;auth_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;avp_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_authorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;policyStoreId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy_store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;policyStoreId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EntityType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EntityId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Document::View&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EntityType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Document&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EntityId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ProjectReport&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization decision: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;auth_response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;decision&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example demonstrates creating a policy store, defining a simple policy, and checking authorization using AVP.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The policy defined in the &lt;code&gt;policy&lt;/code&gt; variable allows a &lt;code&gt;User&lt;/code&gt; called &lt;code&gt;Alice&lt;/code&gt; to perform the action &lt;code&gt;Document::View&lt;/code&gt; only when the specific resource is a &lt;code&gt;Document&lt;/code&gt; with an ID of &lt;code&gt;ProjectReport&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can see in the &lt;code&gt;is_authorized&lt;/code&gt; call, you pass in information about the principal, action, and resource, and then get an authorization decision.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice how similar this is to AWS' IAM policies! Within AVP, you can define many different policies, and then say you have an API, you can pass the information about the principal and what they are accessing from each API call into an &lt;code&gt;is_authorized&lt;/code&gt; call to determine whether to allow the request to be returned as successful or not!&lt;/p&gt;

&lt;h2&gt;
  
  
  AVP vs. Traditional Authorization Methods
&lt;/h2&gt;

&lt;p&gt;Compared to traditional in-app authorization, AVP offers several advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Externalized authorization logic, simplifying application code&lt;/li&gt;
&lt;li&gt;Fine-grained, context-aware access control&lt;/li&gt;
&lt;li&gt;Centralized policy management&lt;/li&gt;
&lt;li&gt;Real-time authorization decisions&lt;/li&gt;
&lt;li&gt;Built-in policy analysis and auditing capabilities&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Best Practices and Tips
&lt;/h2&gt;

&lt;p&gt;When using Amazon Verified Permissions, consider the following best practices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Design your authorization model carefully before implementation&lt;/li&gt;
&lt;li&gt;Use policy templates to standardize and simplify policy creation&lt;/li&gt;
&lt;li&gt;Regularly audit and analyze your policies&lt;/li&gt;
&lt;li&gt;Leverage AVP’s integration capabilities with other AWS services&lt;/li&gt;
&lt;li&gt;Use the test bench feature to validate policies before deployment&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;To optimize AVP usage:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use bulk authorization when possible to reduce API calls&lt;/li&gt;
&lt;li&gt;Implement response caching for frequently accessed resources&lt;/li&gt;
&lt;li&gt;Design your policies to be as specific as possible to improve evaluation speed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Areas for Additional Consideration
&lt;/h2&gt;

&lt;p&gt;As with any technology solution, there are always bound to be downsides and considerations to make.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multi-cloud and hybrid-cloud limitations:

&lt;ul&gt;
&lt;li&gt;As a single identity provider, AVP has limitations in interoperability across the identity stack and in a multi-cloud world.&lt;/li&gt;
&lt;li&gt;Additional solutions may be needed to integrate AVP with on-premises or multi-cloud environments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;While Cedar is open-source completely, it is something released and maintained by AWS. So, if you are worried about that type of lock-in or dependency, it's important to consider this, as AVP is fully reliant on it. I think AWS has done a good job getting it out into the community, where you could decouple this from AVP if needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Amazon Verified Permissions is a powerful service that can enhance the security and manageability of your custom applications. By externalizing and centralizing authorization logic, AVP allows developers to focus on core application functionality while ensuring robust, fine-grained access control. As applications become more complex and security requirements become more stringent, services like AVP will have an increasingly crucial role in maintaining secure and compliant applications.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>policy</category>
      <category>authz</category>
      <category>permissions</category>
    </item>
    <item>
      <title>Using Kyverno Policies for Kubernetes Governance</title>
      <dc:creator>Matt Adorjan</dc:creator>
      <pubDate>Fri, 31 Dec 2021 23:58:15 +0000</pubDate>
      <link>https://dev.to/mda590/using-kyverno-policies-for-kubernetes-governance-3e17</link>
      <guid>https://dev.to/mda590/using-kyverno-policies-for-kubernetes-governance-3e17</guid>
      <description>&lt;p&gt;&lt;a href="https://kyverno.io/" rel="noopener noreferrer"&gt;Kyverno&lt;/a&gt; is a great tool that can be installed into any Kubernetes cluster, allowing cluster administrators to enforce policies for resources in the cluster, and even modify resources before they are applied. Kyverno can be used to ensure deployments are secure, ensure deployments meet certain organizational criteria (e.g. define a cost center label), or even ensure all deployments mount a common volume.&lt;/p&gt;

&lt;p&gt;Kyverno works by deploying a pod and services into your existing cluster. It creates multiple Admission Webhooks in the cluster. These webhooks are responsible for handling API requests coming in to Kubernetes and either validating something from the request (&lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook" rel="noopener noreferrer"&gt;Validating Admission Webhook&lt;/a&gt;, or modifying the request before it is applied (&lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook" rel="noopener noreferrer"&gt;Mutating Admission Webhook&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In the diagram below, you can see where in the process of an API call to Kubernetes, each of the Mutating Admission and Validating Admission webhooks will run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasp3g8ei6l5ck21ipxt2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasp3g8ei6l5ck21ipxt2.png" alt="Admission Controller Phases"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;All of the Kubernetes Manifests and Kyverno Policies are available in &lt;a href="https://github.com/mda590/do-k8s-2021-challenge" rel="noopener noreferrer"&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Kyverno
&lt;/h2&gt;

&lt;p&gt;Getting started with Kyverno is pretty simple. While there are a lot of knobs that can be turned to configure Kyverno, the initial default goes a long way. &lt;em&gt;I deployed this into my DigitalOcean Kubernetes cluster.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To install, I simply ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ helm repo add kyverno https://kyverno.github.io/kyverno/
$ helm repo update
$ helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I now have a single Kyverno pod running in the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get pods -n kyverno
NAME                       READY   STATUS    RESTARTS   AGE
kyverno-6d94754db4-tdl9s   1/1     Running   0          5s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Policies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Anatomy of a basic policy
&lt;/h3&gt;

&lt;p&gt;Policies can be written with many different options in Kyverno. The most basic policies can be written to check values of specific field(s) within an API request to Kubernetes, and make a decision whether the request should be allowed or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Require specific pod labels
&lt;/h3&gt;

&lt;p&gt;This example requires specific labels to be set on a pod prior to creating those resources. One of the great benefits Kyverno provides is that you can specify &lt;code&gt;Pod&lt;/code&gt; as the resource kind, but it will also check against the policy whenever creating resources which will end up creating pods (Deployment, StatefulSet, etc.)&lt;/p&gt;

&lt;p&gt;The below example policy requires that all pods have the &lt;code&gt;labels.acmecorp.com/costCenter&lt;/code&gt; and &lt;code&gt;labels.acmecorp.com/department&lt;/code&gt; labels. They can be set to any value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kyverno.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;require-business-labels&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Require Business Labels&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/category&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Best Practices&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;medium&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/subject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod, Label&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;Define required labels used by our internal business processes to understand which applications&lt;/span&gt;
      &lt;span class="s"&gt;are running in each cluster, and used to handle chargeback activities for resources consumed&lt;/span&gt;
      &lt;span class="s"&gt;by this specific application.&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;validationFailureAction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;enforce&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check-for-business-labels&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kinds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
    &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;labels&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;`labels.acmecorp.com/costCenter`&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;`labels.acmecorp.com/department`&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;are&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;required."&lt;/span&gt;
      &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;labels.acmecorp.com/costCenter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?*"&lt;/span&gt;
            &lt;span class="na"&gt;labels.acmecorp.com/department&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example Policy Tests:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mda590/do-k8s-2021-challenge/blob/main/deployments/01_denied.yaml" rel="noopener noreferrer"&gt;Example Deployment which will be denied under this policy.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mda590/do-k8s-2021-challenge/blob/main/deployments/01_allowed.yaml" rel="noopener noreferrer"&gt;Example Deployment which will be allowed under this policy.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Demo showing policy in cluster:
&lt;/h4&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/yd_f8XIgLfw"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  Require the use of a specific container registry
&lt;/h3&gt;

&lt;p&gt;This policy checks for 2 important items: 1. images specified in a pod definition must be from a specific container registry (in this case, from the DigitalOcean registry); and 2. images cannot have the &lt;code&gt;latest&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kyverno.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;restrict-image-registries&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restrict Image Registries and Latest&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/category&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Best Practices&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;medium&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/subject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;Requires all images for pods be sourced from the Digital Ocean Container Registry. Any other&lt;/span&gt;
      &lt;span class="s"&gt;image sources are denied.&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;validationFailureAction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;enforce&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;validate-registries&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kinds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
    &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;registry."&lt;/span&gt;
      &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;registry.digitalocean.com/*"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;validate-image-tag&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kinds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
    &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Must&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;use&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tag&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;`latest`&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;images."&lt;/span&gt;
      &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!*:latest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example Policy Tests:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mda590/do-k8s-2021-challenge/blob/main/deployments/02_denied.yaml" rel="noopener noreferrer"&gt;Example Deployment which will be denied under this policy.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mda590/do-k8s-2021-challenge/blob/main/deployments/02_allowed.yaml" rel="noopener noreferrer"&gt;Example Deployment which will be allowed under this policy.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Demo showing policy in cluster:
&lt;/h4&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Sb0zzsif7ZM"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  Require a runAsUser be specified
&lt;/h3&gt;

&lt;p&gt;This policy requires that every container specified within a pod has a &lt;code&gt;runAsUser&lt;/code&gt; defined and that the value is greater than &lt;code&gt;0&lt;/code&gt;, meaning the container cannot run as root. In reality, there are additional items you will probably want to check in a policy like this, but this provides a good place to get started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kyverno.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;require-pod-runasuser&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Require the RunAsUser to be Specified&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/category&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Best Practices&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;medium&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/subject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
    &lt;span class="na"&gt;policies.kyverno.io/description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;Requires Pods to specify as runAsUser value within their containers which are not root.&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;validationFailureAction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;enforce&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check-userid&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kinds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
    &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
        &lt;span class="s"&gt;The field spec.containers.*.securityContext.runAsUser must specified and greater than zero.&lt;/span&gt;
      &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example Policy Tests:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mda590/do-k8s-2021-challenge/blob/main/deployments/03_denied.yaml" rel="noopener noreferrer"&gt;Example Deployment which will be denied under this policy.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mda590/do-k8s-2021-challenge/blob/main/deployments/03_allowed.yaml" rel="noopener noreferrer"&gt;Example Deployment which will be allowed under this policy.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Demo showing policy in cluster:
&lt;/h4&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qTVkgwBQcA0"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Overall, this is meant to be a couple basic examples of using policies with Kyverno in Kubernetes. You can certainly get much more complex, or implement a policy which mutates a resource, to keep resources in your cluster compliant with your rules.&lt;/p&gt;

&lt;p&gt;If you end up trying Kyverno and find out you need something more complex, take a look at Gatekeeper. The &lt;a href="https://open-policy-agent.github.io/gatekeeper/website/docs/" rel="noopener noreferrer"&gt;Gatekeeper&lt;/a&gt; project works very similar to Kyverno, except it allows for defining policies in Rego language, which adds complexity but allow for additional customization.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>kyverno</category>
      <category>policy</category>
      <category>governance</category>
    </item>
    <item>
      <title>Trying out AWS Controllers for Kubernetes (ACK)</title>
      <dc:creator>Matt Adorjan</dc:creator>
      <pubDate>Wed, 25 Aug 2021 00:13:50 +0000</pubDate>
      <link>https://dev.to/mda590/trying-out-aws-controllers-for-kubernetes-ack-1897</link>
      <guid>https://dev.to/mda590/trying-out-aws-controllers-for-kubernetes-ack-1897</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws-controllers-k8s.github.io/community/"&gt;AWS Controllers for Kubernetes (ACK)&lt;/a&gt; allows creating AWS resources via the same process you use to deploy other resources in Kubernetes. ACK uses the Kubernetes controller model to interact with AWS APIs. Once the ACK service controller for a specific service is deployed, you can leverage Kubernetes Custom Resource Definitions (CRDs) to declare specific AWS resources in YAML manifests. You then send them to the Kubernetes API server and the specified AWS resources are provisioned within your AWS account.&lt;/p&gt;

&lt;p&gt;When I initially heard the news about AWS Controllers for Kubernetes, I was immediately struck by a few previous challenges where having AWS resources tied directly to other Kubernetes deployments would be immensely helpful. I think the key for using ACK is understanding when it makes sense to use them. Most organizations have mature processes for provisioning cloud infrastructure using tools like CloudFormation or Terraform. By introducing a new way of provisioning resources, you introduce an additional place where you now need to govern standards in terms of naming/tagging/security config, validate permissions for the controller follow least privilege, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;p&gt;In my opinion, there are only a few reasons to use ACK to deploy resources and a longer list of situations where you probably want to avoid using ACK. Obviously, this is all very dependent on your organization and your use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use ACK
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Managing AWS resources which are tied to the lifecycle of Kubernetes resources - there are many use cases where you may want to maintain resources alongside your Kubernetes deployments, or specify them in your Helm Chart. For example, a use case that will be helpful on day 1 for me is the ability to create SQS queues alongside deployments in Kubernetes which are set to scale based on the new SQS queue's length.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When not to use ACK
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AWS resources are going to be primarily used outside of Kubernetes - this is not a replacement for an infrastructure as code solution like CloudFormation or Terraform.&lt;/li&gt;
&lt;li&gt;Data retention is required - this is a grey area, as you can definitely create data stores using ACK and there might be good cases for this. However, it is important to understand how simply deleting the AWS resource object in Kubernetes accidentally would cause both the deletion of the AWS resource and all of its associated data.&lt;/li&gt;
&lt;li&gt;ACK controllers don't expose required parameters - if the controller doesn't expose specific parameters you need set on a resource, you should create the resource using another method to avoid double work. For example, if you need S3 Public Access to be turned off, it's not an available parameter, so ACK isn't a good option.&lt;/li&gt;
&lt;li&gt;You want a way to expose resource deployments to developers and they already know Kubernetes - just because a developer is familiar with how Kubernetes resources work, if the resources are not directly tied to a Kubernetes deployment, it doesn't make sense to manage those resources with ACK. It makes more sense for developers to learn CloudFormation or Terraform or to expose resource creation to them using something like AWS Service Catalog.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing a deployment model
&lt;/h2&gt;

&lt;p&gt;ACK calls these &lt;code&gt;installScope&lt;/code&gt; and the options are either &lt;code&gt;cluster&lt;/code&gt; or &lt;code&gt;namespace&lt;/code&gt;. There are some pros and cons for each option.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cluster:

&lt;ul&gt;
&lt;li&gt;Pros: Only need to run one copy of each controller in the cluster, therefore reducing effort required to manage these components.&lt;/li&gt;
&lt;li&gt;Cons: Permissions for the IAM credentials used by each controller will need to be broad to accommodate all of the possible ways a resource needs to be created anywhere in the cluster.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Namespace:

&lt;ul&gt;
&lt;li&gt;Pros: Can get finer grained with controller configuration and IAM permissions that are used when the controller creates resources.&lt;/li&gt;
&lt;li&gt;Cons: Need to manage each controller in all namespaces, which can add operational overhead (e.g. need to run upgrades across all namespaces instead of in just 1 place).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm a big fan of the "shared service" model in multi-tenant clusters, and will likely use the &lt;code&gt;cluster&lt;/code&gt; option here. I think as long as you have proper governance in place within the cluster, you can centrally manage all of your components once and make them available to all users in the cluster. See the last section of this post for more information on an approach for governance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with ACK's S3 Controller
&lt;/h2&gt;

&lt;p&gt;I initially started following the &lt;a href="https://aws-controllers-k8s.github.io/community/user-docs/install/#helm-recommended"&gt;Install instructions from the ACK docs&lt;/a&gt;, specifically using the Helm chart. Looking at the &lt;a href="https://gallery.ecr.aws/aws-controllers-k8s/s3-chart"&gt;S3 controller Helm Chart in ECR&lt;/a&gt;, the latest version is &lt;code&gt;v0.0.2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HELM_EXPERIMENTAL_OCI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SERVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;s3
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RELEASE_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v0.0.2
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CHART_EXPORT_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/chart
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CHART_REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public.ecr.aws/aws-controllers-k8s/&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-chart&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CHART_REF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$CHART_REPO&lt;/span&gt;:&lt;span class="nv"&gt;$RELEASE_VERSION&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ACK_K8S_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ack-system

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$CHART_EXPORT_PATH&lt;/span&gt;

helm chart pull &lt;span class="nv"&gt;$CHART_REF&lt;/span&gt;
helm chart &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;$CHART_REF&lt;/span&gt; &lt;span class="nt"&gt;--destination&lt;/span&gt; &lt;span class="nv"&gt;$CHART_EXPORT_PATH&lt;/span&gt;

kubectl create namespace &lt;span class="nv"&gt;$ACK_K8S_NAMESPACE&lt;/span&gt;

helm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="nv"&gt;$ACK_K8S_NAMESPACE&lt;/span&gt; ack-&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-controller&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;$CHART_EXPORT_PATH&lt;/span&gt;/ack-&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-controller&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worked overall, but as I started deploying a test S3 bucket, a lot of the &lt;code&gt;Specs&lt;/code&gt; &lt;a href="https://aws-controllers-k8s.github.io/community/reference/S3/v1alpha1/Bucket/#spec"&gt;listed in the docs&lt;/a&gt; were generating errors and not working. For example, my bucket manifest is below. &lt;code&gt;v0.0.2&lt;/code&gt; did not have any support for &lt;code&gt;tagging&lt;/code&gt; so this would create a bucket without tags and throw a &lt;code&gt;not implemented&lt;/code&gt; error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3.services.k8s.aws/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bucket&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-s3-matt-bucket&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tagging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tagSet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CostCenter&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Development&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-s3-matt-bucket&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After trying to understand what was going on, I realized that both the Helm Chart and the Docker image available in ECR were out of date. Looking at the s3-controller repository, changes were actively being made but there were no releases indicating what commit the &lt;code&gt;v0.0.2&lt;/code&gt; versions were tied to.&lt;/p&gt;

&lt;p&gt;As a next step, I decided to build a newer Docker image and use the latest Helm chart from the repository to deploy the controller. This ended up being a bit more difficult than I anticipated. The ACK solution is designed to be very modular. The pro of this design is that it's very easy to add new services to ACK. The biggest con is that it is a bit confusing to figure out how everything fits together as someone new to the project.&lt;/p&gt;

&lt;p&gt;After reading through the documentation a bit more and reviewing all of the different repositories in the &lt;code&gt;aws-controllers-k8s&lt;/code&gt; org, I found the &lt;code&gt;code-generator&lt;/code&gt; repository which contains the proper scripts to generate new Docker images for services based on the latest commits on a service repository.&lt;/p&gt;

&lt;p&gt;To build a new S3 image:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the following to clone the &lt;code&gt;code-generator&lt;/code&gt; repo and run the build script for &lt;code&gt;s3&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/aws-controllers-k8s/code-generator.git
&lt;span class="nb"&gt;cd &lt;/span&gt;code-generator/scripts/
./build-controller-image.sh s3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Tag the newly generated image and push it to my own ECR repo.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag &amp;lt;image-tag&amp;gt; public.ecr.aws/&amp;lt;repository&amp;gt;/s3-ack:&amp;lt;tag&amp;gt;
docker push public.ecr.aws/&amp;lt;repository&amp;gt;/s3-ack:&amp;lt;tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the following to clone the &lt;code&gt;s3-controller&lt;/code&gt; repository:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/aws-controllers-k8s/s3-controller.git
&lt;span class="nb"&gt;cd &lt;/span&gt;s3-controller/helm/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Assuming you've already deployed the Helm chart earlier, you will need to upgrade the chart using the same name as before but instead pointing to the locally cloned copy. The example below upgrades a Helm chart called &lt;code&gt;ack-s3-controller&lt;/code&gt; installed in namespace &lt;code&gt;ack-system&lt;/code&gt; and sources the Helm chart from the current directory (&lt;code&gt;.&lt;/code&gt;). It also sets the &lt;code&gt;image.repository&lt;/code&gt; and &lt;code&gt;image.tag&lt;/code&gt; values to the new location in ECR from step #2.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm upgrade ack-s3-controller &lt;span class="nb"&gt;.&lt;/span&gt;  &lt;span class="nt"&gt;--namespace&lt;/span&gt; ack-system &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--set&lt;/span&gt; image.repository&lt;span class="o"&gt;=&lt;/span&gt;public.ecr.aws/&amp;lt;repository&amp;gt;/s3-ack,image.tag&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, you should now be able to create a new S3 bucket leveraging the latest features available in the documentation. In my experience, as soon as I deployed the new version and used the S3 Bucket YAML file listed above, a new S3 bucket was deployed with the expected tags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggestions
&lt;/h2&gt;

&lt;p&gt;The ACK project has a very in depth review of their releases and versioning process &lt;a href="https://aws-controllers-k8s.github.io/community/releases/"&gt;here&lt;/a&gt;. It is very thorough and follows a lot of standards you would expect for a solution of this nature. One of the items the documentation makes very clear is that each controller is on its own release and maintenance cycle. This also makes sense, given the amount of different service controllers that will be needed.&lt;/p&gt;

&lt;p&gt;All of this being said, my suggestion is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow a standardized release process for all of the controllers. Some controllers have releases defined in GitHub which match up with Docker images and Helm charts, some don't (as we saw with S3).&lt;/li&gt;
&lt;li&gt;If the service controller documentation is being updated on the Docs website, make sure there is an actual released Docker image and Helm chart available which allows the usage of what the Docs are referencing.&lt;/li&gt;
&lt;li&gt;Document the release versions in a centralized location on the Docs website. &lt;a href="https://aws-controllers-k8s.github.io/community/services/"&gt;This page&lt;/a&gt; would be a great place to list the latest released version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't think it's a huge ask to attach some simple release processes to each of the controller repositories which handle the above. I'm completely cognizant of the fact that these are all still in alpha and may not be ready for "stable" tags, but I think this simple change significantly lowers the barrier to entry and will allow others in the community to try out these controllers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Governing resource creation by ACK with Gatekeeper
&lt;/h2&gt;

&lt;p&gt;You may want to govern that AWS resources are created using specified guardrails when using ACK. One way you could do this is to try to customize the IAM policy attached to the controllers to restrict creation of resources unless they meet certain conditions. This works well but different resources offer different conditions meaning you may or may not be able to restrict creation based on the parameters you would like. Also, error messages returned from AWS for Access Denied are not passed through to the end user, leaving them blind to issues caused by IAM restrictions.&lt;/p&gt;

&lt;p&gt;In the world of Kubernetes, &lt;a href="https://open-policy-agent.github.io/gatekeeper/website/docs/"&gt;Gatekeeper&lt;/a&gt; can fill this gap for us when using ACK. Because AWS resources to be deployed with ACK are translated into a standard JSON format when submitting to the Kubernetes API, we can write policies in rego which are then enforced using Gatekeeper.&lt;/p&gt;

&lt;p&gt;I will leave a full Gatekeeper tutorial for other posts that already exist, but will post a sample Gatekeeper Template and Constraint below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Gatekeeper Template and Constraint - S3 Standards
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;template.yaml&lt;/code&gt; - this defines the Constraint Template. You can see we are checking that the S3 bucket name starts with a specific string and that a specific tag is present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;templates.gatekeeper.sh/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConstraintTemplate&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bucketdefaultrequirements&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Requires S3 buckets created by ACK match standards.&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;crd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bucketDefaultRequirements&lt;/span&gt;
      &lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Schema for the `parameters` field&lt;/span&gt;
        &lt;span class="na"&gt;openAPIV3Schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
          &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;bucketStartsWith&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
            &lt;span class="na"&gt;requiredTagKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admission.k8s.gatekeeper.sh&lt;/span&gt;
      &lt;span class="na"&gt;rego&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;package bucketdefaultrequirements&lt;/span&gt;

        &lt;span class="s"&gt;violation[{"msg": msg}] {&lt;/span&gt;
          &lt;span class="s"&gt;namingConventionStartsWith := input.parameters.bucketStartsWith&lt;/span&gt;

          &lt;span class="s"&gt;value := input.review.object.spec.name&lt;/span&gt;

          &lt;span class="s"&gt;# Check if the Bucket Name follows our naming convention&lt;/span&gt;
          &lt;span class="s"&gt;not startswith(value, namingConventionStartsWith)&lt;/span&gt;

          &lt;span class="s"&gt;# Construct an error message to return to the user.&lt;/span&gt;
          &lt;span class="s"&gt;msg := sprintf("Bucket name does not follow proper format; found `%v`; needs to start with `%v`.", [value, namingConventionStartsWith])&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;

        &lt;span class="s"&gt;violation[{"msg": msg}] {&lt;/span&gt;
          &lt;span class="s"&gt;requiredTagKey := input.parameters.requiredTagKey&lt;/span&gt;
          &lt;span class="s"&gt;value := input.review.object.spec.tagging.tagSet&lt;/span&gt;
          &lt;span class="s"&gt;not contains(value, requiredTagKey)&lt;/span&gt;
          &lt;span class="s"&gt;msg := sprintf("%v tag is missing.", [requiredTagKey])&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;

        &lt;span class="s"&gt;contains(tagKeys, elem) {&lt;/span&gt;
          &lt;span class="s"&gt;tagKeys[_]["key"] = elem&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;constraint.yaml&lt;/code&gt; - this defines the actual constraint which uses the template created above. We can create a new constraint to be used across the entire cluster (like below) or we can create specific namespace scoped constraints for this rule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;constraints.gatekeeper.sh/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bucketDefaultRequirements&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3-buckets-must-meet-base-requirements&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kinds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3.services.k8s.aws"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;kinds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bucket"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;bucketStartsWith&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matt-s3-"&lt;/span&gt;
    &lt;span class="na"&gt;requiredTagKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CostCenter"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the above constraint fails and I try to create an S3 bucket called &lt;code&gt;test-s3-matt-bucket&lt;/code&gt; without a CostCenter tag, I get the following friendly message returned by the Kubernetes API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;error when creating &lt;span class="s2"&gt;"bucket.yaml"&lt;/span&gt;: admission webhook &lt;span class="s2"&gt;"validation.gatekeeper.sh"&lt;/span&gt; denied the request: 
&lt;span class="o"&gt;[&lt;/span&gt;s3-buckets-must-meet-base-requirements] CostCenter tag is missing.
&lt;span class="o"&gt;[&lt;/span&gt;s3-buckets-must-meet-base-requirements] Bucket name does not follow proper format&lt;span class="p"&gt;;&lt;/span&gt; found &lt;span class="sb"&gt;`&lt;/span&gt;test-s3-matt-bucket&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; needs to start with &lt;span class="sb"&gt;`&lt;/span&gt;matt-s3-&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope that this has been helpful in some way! ACK is a great step forward for integrating AWS resources with the Kubernetes deployment lifecycle which many developers are already very familiar with. It's still early days, and like everything that comes out of AWS, I am positive customer obsession will continue driving the ACK project towards full API parity when deploying AWS resources in Kubernetes.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ack</category>
      <category>kubernetes</category>
      <category>eks</category>
    </item>
  </channel>
</rss>
