Skip to main content

2 posts tagged with "Cert-Manager"

View All Tags

· 3 min read
Byju Luckose

In this blog post, we'll walk through building a cloud-native Spring Boot application that runs on Amazon EKS (Elastic Kubernetes Service) and securely uploads files to an Amazon S3 bucket using IAM Roles for Service Accounts (IRSA). This allows your microservice to access AWS services like S3 without embedding credentials.

Why IRSA?

Traditionally, applications used access key/secret pairs for AWS SDKs. In Kubernetes, this is insecure and hard to manage. IRSA allows you to:

  • Grant fine-grained access to AWS resources
  • Avoid storing AWS credentials in your app
  • Rely on short-lived credentials provided by EKS

Overview

Here's the architecture we'll implement:

  1. Spring Boot app runs in EKS
  2. The app uses AWS SDK v2
  3. IRSA provides access to S3

Step 1: Create an IAM Policy for S3 Access

Create a policy named S3UploadPolicy with permissions for your bucket:


{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}

Step 2: Create an IAM Role for EKS

Use eksctl to create a service account and bind it to the IAM role:


eksctl create iamserviceaccount \
--name s3-uploader-sa \
--namespace default \
--cluster your-cluster-name \
--attach-policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/S3UploadPolicy \
--approve \
--override-existing-serviceaccounts

Step 3: Spring Boot Setup

Add AWS SDK Dependency


<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>

Java Code to Upload to S3


import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import java.io.InputStream;

@Service
public class S3Uploader {

private final S3Client s3Client;

public S3Uploader() {
this.s3Client = S3Client.builder()
.region(Region.EU_CENTRAL_1)
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
}

public void uploadFile(String bucketName, String key, InputStream inputStream, long contentLength) {
PutObjectRequest putRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.build();

s3Client.putObject(putRequest, RequestBody.fromInputStream(inputStream, contentLength));
}
}

DefaultCredentialsProvider automatically picks up credentials from the environment, including those provided by IRSA in EKS.

Step 4: Kubernetes Deployment

Define the Service Account (optional if created via eksctl):


apiVersion: v1
kind: ServiceAccount
metadata:
name: s3-uploader-sa
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/<IRSA_ROLE_NAME>


apiVersion: apps/v1
kind: Deployment
metadata:
name: s3-upload-microservice
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: s3-upload-microservice
template:
metadata:
labels:
app: s3-upload-microservice
spec:
serviceAccountName: s3-uploader-sa
containers:
- name: app
image: 123456789012.dkr.ecr.eu-central-1.amazonaws.com/s3-uploader:latest
ports:
- containerPort: 8080

Final Thoughts

You now have a secure, cloud-native Spring Boot application that uploads to S3 using best practices with AWS and Kubernetes. IRSA removes the need for credentials in your code and aligns perfectly with GitOps, DevSecOps, and Zero Trust principles.

Let your microservices speak AWS securely — the cloud-native way!

· 4 min read
Byju Luckose

When deploying applications in an Amazon EKS (Elastic Kubernetes Service) environment, securing them with SSL/TLS is essential to protect sensitive data and ensure secure communication. One of the most popular and free methods to obtain TLS certificates is through Let’s Encrypt. This guide walks you through the process of setting up TLS certificates on an EKS cluster using Cert-Manager and NGINX Ingress Controller.

Prerequisites

Before starting, ensure you have the following:

  • An EKS Cluster set up with worker nodes.
  • kubectl configured to access your cluster.
  • A registered domain name pointing to the EKS load balancer.
  • NGINX Ingress Controller installed on the cluster.

Step 1: Install Cert-Manager

Cert-Manager automates the management of TLS certificates within Kubernetes.

Install Cert-Manager

Run the following command to apply the official Cert-Manager manifests:


kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.2/cert-manager.yaml

Verify the pods:


kubectl get pods --namespace cert-manager

You should see the following pods running:

  • cert-manager

  • cert-manager-cainjector

  • cert-manager-webhook

Step 2: Create a ClusterIssuer

A ClusterIssuer is a resource in Kubernetes that defines how Cert-Manager should obtain certificates. We’ll create one using Let’s Encrypt’s production endpoint.

ClusterIssuer YAML File:

Create a file named letsencrypt-cluster-issuer.yaml with the following content:

yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your.email@example.com # Change this to your email
privateKeySecretRef:
name: letsencrypt-prod-private-key
solvers:
- http01:
ingress:
class: nginx

Apply the YAML:


kubectl apply -f letsencrypt-cluster-issuer.yaml

Verify that the ClusterIssuer is created successfully:


kubectl get clusterissuer

Step 3: Create an Ingress Resource with TLS

The Ingress resource will route external traffic to services within the cluster and configure TLS.

Ingress YAML File:

Create a file named ingress.yaml with the following content:

yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
rules:
- host: yourdomain.com # Replace with your domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
tls:
- hosts:
- yourdomain.com
secretName: my-app-tls

Apply the YAML:


kubectl apply -f ingress.yaml

Step 4: Verify the TLS Certificate

Check the status of the certificate request:


kubectl describe certificate my-app-tls

You should see a message indicating that the certificate was successfully issued. Cert-Manager will create a Kubernetes Secret named my-app-tls that contains the TLS certificate and key.

List the secrets to verify:


kubectl get secrets

You should see my-app-tls listed.

Step 5: Test the HTTPS Connection

Once the certificate is issued, test the connection:

  1. Open a browser and navigate to https://yourdomain.com.

  2. Verify that the connection is secure by checking for a valid TLS certificate.

Troubleshooting Tips:

  • Ensure the domain correctly resolves to the EKS load balancer.

  • Check for errors in the Cert-Manager logs using:


kubectl logs -n cert-manager -l app=cert-manager

Step 6: Renewing and Managing Certificates

Let’s Encrypt certificates are valid for 90 days. Cert-Manager automatically renews them before expiry.

To check if the renewal is working:


kubectl get certificates

Look for the renewal time and ensure it’s set before the expiration date.

Step 7: Clean Up (Optional)

If you want to remove the configurations:


kubectl delete -f ingress.yaml
kubectl delete -f letsencrypt-cluster-issuer.yaml
kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.2/cert-manager.yaml

Conclusion

Congratulations! You have successfully secured your applications on an EKS cluster using Let’s Encrypt certificates. With the help of Cert-Manager, you can automate certificate issuance, management, and renewal, ensuring your applications always maintain secure communications. By following this guide, you have taken a significant step towards enhancing the security posture of your Kubernetes environment.