<?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>Forem: Marco Ferraioli</title>
    <description>The latest articles on Forem by Marco Ferraioli (@paranoiasystem).</description>
    <link>https://forem.com/paranoiasystem</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%2F94936%2Fac9fc731-6d97-4d0b-87a8-cc90446d0baa.jpeg</url>
      <title>Forem: Marco Ferraioli</title>
      <link>https://forem.com/paranoiasystem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/paranoiasystem"/>
    <language>en</language>
    <item>
      <title>Automatic Management of AWS ECR Credentials in a Kubernetes Cluster</title>
      <dc:creator>Marco Ferraioli</dc:creator>
      <pubDate>Wed, 21 Jun 2023 11:55:00 +0000</pubDate>
      <link>https://forem.com/paranoiasystem/automatic-management-of-aws-ecr-credentials-in-a-kubernetes-cluster-2pgn</link>
      <guid>https://forem.com/paranoiasystem/automatic-management-of-aws-ecr-credentials-in-a-kubernetes-cluster-2pgn</guid>
      <description>&lt;p&gt;In the course of my work with &lt;strong&gt;&lt;em&gt;AWS ECR (Elastic Container Registry)&lt;/em&gt;&lt;/strong&gt;, I ran into a problem: The repository access key expires every six hours. Working with a non-AWS Kubernetes test cluster, I had to constantly update these credentials manually, a repetitive and tedious process.&lt;/p&gt;

&lt;p&gt;From this experience came the idea to create a tool that automated this process: &lt;strong&gt;&lt;em&gt;&lt;a href="https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater"&gt;k8s-aws-ecr-secret-updater&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;. This tool is a Kubernetes cronjob, designed to automatically update the AWS ECR repository access credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cronjob Configuration
&lt;/h2&gt;

&lt;p&gt;The YAML code to create the cronjob consists of several parts, which I will now analyze piece by piece:&lt;/p&gt;

&lt;h3&gt;
  
  
  A Role that has permission to get, create, and delete secrets and get and update ServiceAccounts.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&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;k8sawsecrsecretupdater&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;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;"&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="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;secrets"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&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;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delete"&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;"&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="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;serviceaccounts"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&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;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;patch"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A key component of this configuration is the &lt;strong&gt;&lt;em&gt;k8sawsecrsecretupdater&lt;/em&gt;&lt;/strong&gt; role. This role is fundamental for authorization within the Kubernetes namespace, allowing the cronjob to perform specific operations on certain resources.&lt;/p&gt;

&lt;p&gt;In particular, the &lt;strong&gt;&lt;em&gt;k8sawsecrsecretupdater&lt;/em&gt;&lt;/strong&gt; role has the following permissions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It has permissions to get (&lt;strong&gt;&lt;em&gt;get&lt;/em&gt;&lt;/strong&gt;), create (&lt;strong&gt;&lt;em&gt;create&lt;/em&gt;&lt;/strong&gt;), and delete (&lt;strong&gt;&lt;em&gt;delete&lt;/em&gt;&lt;/strong&gt;) &lt;strong&gt;&lt;em&gt;Secrets&lt;/em&gt;&lt;/strong&gt;. This is crucial because the cronjob needs to be able to create and delete AWS ECR credentials, which are stored as secrets in Kubernetes.&lt;/li&gt;
&lt;li&gt;It has permissions to get (&lt;strong&gt;&lt;em&gt;get&lt;/em&gt;&lt;/strong&gt;) and update (&lt;strong&gt;&lt;em&gt;patch&lt;/em&gt;&lt;/strong&gt;) &lt;strong&gt;&lt;em&gt;ServiceAccounts&lt;/em&gt;&lt;/strong&gt;. The cronjob needs to be able to manage service accounts in order to associate the AWS ECR credentials with the service that runs the cronjob.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Creating a specific role for these operations ensures that the cronjob has exactly the permissions it needs to do its job, without granting it access to unnecessary resources. This approach is in line with the principle of least privilege, a common security practice that limits access to resources only to what is strictly necessary to perform a specific task. This helps to minimize the potential impact of a possible attack.&lt;/p&gt;

&lt;h3&gt;
  
  
  ServiceAccount to be used by the job and cronjob.
&lt;/h3&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;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;ServiceAccount&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;k8sawsecrsecretupdater&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  RoleBinding to associate the Role with the ServiceAccount.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RoleBinding&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&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;k8sawsecrsecretupdater&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&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;ServiceAccount&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;k8sawsecrsecretupdater&lt;/span&gt;
&lt;span class="na"&gt;roleRef&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;Role&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;k8sawsecrsecretupdater&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Job that creates the secret.
&lt;/h3&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;batch/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;Job&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;k8sawsecrsecretupdater&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;backoffLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
  &lt;span class="na"&gt;template&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;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;k8sawsecrsecretupdater&lt;/span&gt;
      &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Never&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;k8sawsecrsecretupdater&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/paranoiasystem/k8s-aws-ecr-secret-updater:latest&lt;/span&gt;
        &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&lt;/span&gt;
        &lt;span class="na"&gt;env&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;AWS_ACCOUNT&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YourAwsAccountID'&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;AWS_ACCESS_KEY_ID&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;YourAccessKeyID&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;AWS_SECRET_ACCESS_KEY&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;YourSecretAccessKey&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;AWS_REGION&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;YourRegion&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CronJob that runs the Job every 6 hours.
&lt;/h3&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;batch/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;CronJob&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;k8sawsecrsecretupdater&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;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*/6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
  &lt;span class="na"&gt;successfulJobsHistoryLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;failedJobsHistoryLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;jobTemplate&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;template&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;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;k8sawsecrsecretupdater&lt;/span&gt;
          &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Never&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;k8sawsecrsecretupdater&lt;/span&gt;
            &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/paranoiasystem/k8s-aws-ecr-secret-updater:latest&lt;/span&gt;
            &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&lt;/span&gt;
            &lt;span class="na"&gt;env&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;AWS_ACCOUNT&lt;/span&gt;
              &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YourAwsAccountID'&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;AWS_ACCESS_KEY_ID&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;YourAccess&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;AWS_SECRET_ACCESS_KEY&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;YourSecretAccessKey&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;AWS_REGION&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;YourRegion&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the Docker Image
&lt;/h2&gt;

&lt;p&gt;The cronjob uses a specific Docker image to perform its task. This Docker image is built from the following Dockerfile:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E_c27ifN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rf1v330lps7nk2ob9pb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E_c27ifN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rf1v330lps7nk2ob9pb1.png" alt="Dockerfile" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Dockerfile, starting from an Alpine base image, the necessary tools are installed, including git, bash, curl, openssh, python3, py3-pip, py-cryptography, wget, curl, jq. Also, kubectl and AWSCLI are installed for interaction with Kubernetes and AWS, respectively.&lt;/p&gt;

&lt;p&gt;Subsequently, the working directory is set to /scripts and the contents of the local /scripts directory are copied. Finally, an ENTRYPOINT is defined that starts the entrypoint.sh script when the container is run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution of the Script
&lt;/h2&gt;

&lt;p&gt;When the cronjob is run, it starts the bash script contained in the Docker image. This script checks for the existence of a secret called &lt;code&gt;"regcred"&lt;/code&gt;. If it exists, it deletes it and creates a new one. If it doesn't exist, it creates it. Below is the script:&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="c"&gt;#!/bin/bash&lt;/span&gt;

create_secret&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  kubectl create secret docker-registry regcred &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--docker-server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.dkr.ecr.&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.amazonaws.com &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--docker-username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AWS &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--docker-password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Check if the secret exists&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;kubectl get secret regcred&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
  &lt;span class="c"&gt;# If it exists, delete it&lt;/span&gt;
  kubectl delete secret regcred
  &lt;span class="c"&gt;# Create the secret again&lt;/span&gt;
  create_secret
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="c"&gt;# If it doesn't exist, create it&lt;/span&gt;
  create_secret
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing k8s-aws-ecr-secret-updater on Kubernetes
&lt;/h2&gt;

&lt;p&gt;To use the &lt;strong&gt;&lt;em&gt;&lt;a href="https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater"&gt;k8s-aws-ecr-secret-updater&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; in your Kubernetes environment, you need to follow some simple steps.&lt;/p&gt;

&lt;p&gt;Let's start by cloning the project's GitHub repository onto your local system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to open and edit the &lt;strong&gt;&lt;em&gt;install.yaml&lt;/em&gt;&lt;/strong&gt; file present in the repository. In this file, you will need to set the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS_ACCOUNT&lt;/strong&gt;: your AWS account ID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS_ACCESS_KEY_ID&lt;/strong&gt;: your AWS access key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS_SECRET_ACCESS_KEY&lt;/strong&gt;: your AWS secret access key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS_REGION&lt;/strong&gt;: the AWS region where your ECR is located.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have made these changes, save and exit the install.yaml file.&lt;/p&gt;

&lt;p&gt;Now, to install the &lt;strong&gt;&lt;em&gt;&lt;a href="https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater"&gt;k8s-aws-ecr-secret-updater&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; in your Kubernetes cluster, you need to execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;destination_namespace&amp;gt; &lt;span class="nt"&gt;-f&lt;/span&gt; install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to replace &lt;strong&gt;destination_namespace&lt;/strong&gt; with the Kubernetes namespace where you want to install the cronjob.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;This tool eliminates the need for manual updating of credentials, saving time and reducing the risk of errors. I hope this article and the tool I created can be of help to anyone dealing with a similar issue in managing AWS ECR credentials in a Kubernetes cluster.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>secret</category>
      <category>docker</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
