Skip to main content

SSL Certificate Management

This guide covers SSL/TLS certificate management options for MCP Platform, comparing cert-manager and AWS Certificate Manager (ACM) to help you choose the right approach for your deployment.

Overview

MCP Platform supports multiple certificate management approaches depending on your deployment method and requirements:

cert-manager

Best for: Kubernetes deployments, multi-cloud, self-managedAutomatic Let’s Encrypt certificates with full Kubernetes integration

AWS Certificate Manager

Best for: AWS-native deployments, enterprise environmentsManaged SSL certificates with seamless AWS service integration

Comparison Matrix

Featurecert-managerAWS ACM
CostFree (Let’s Encrypt)Free for AWS services
Certificate AuthorityLet’s Encrypt, othersAmazon CA, imported certs
Automatic Renewal✅ Every 60 days✅ Automatic
Wildcard Support✅ DNS-01 challenge✅ DNS validation
Multi-cloud✅ Any Kubernetes❌ AWS only
Private Certificates✅ With private CA✅ AWS Private CA
Setup ComplexityMediumLow
Kubernetes Native✅ Native CRDs❌ External service

cert-manager Configuration

When to Use cert-manager

  • Multi-cloud deployments or non-AWS environments
  • Full control over certificate lifecycle
  • Integration with private CAs or custom issuers
  • Kubernetes-native certificate management

Installation and Setup

1

Install cert-manager

# Add Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
helm repo update

# Install cert-manager with CRDs
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager --create-namespace \
  --set installCRDs=true \
  --version v1.13.0
2

Create ClusterIssuer for Let's Encrypt

# letsencrypt-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # Let's Encrypt production server
    server: https://acme-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    # DNS-01 challenge for wildcard certificates
    - dns01:
        route53:
          region: us-east-1
          # IAM role for Route53 access (recommended with IRSA)
          role: arn:aws:iam::123456789012:role/cert-manager-route53
    # HTTP-01 challenge for single domain certificates
    - http01:
        ingress:
          class: alb  # or nginx
kubectl apply -f letsencrypt-issuer.yaml
3

Configure IAM for Route53 (AWS only)

For DNS-01 challenges with Route53:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:GetChange",
        "route53:ChangeResourceRecordSets",
        "route53:ListHostedZonesByName"
      ],
      "Resource": [
        "arn:aws:route53:::hostedzone/*",
        "arn:aws:route53:::change/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "route53:ListHostedZones",
      "Resource": "*"
    }
  ]
}

MCP Platform Configuration with cert-manager

  • Single Domain
  • Wildcard Certificate
Standard deployment with single domain:
# values-cert-manager.yaml
ingress:
  enabled: true
  className: "alb"  # or nginx
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    # For ALB
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/ssl-redirect: '443'
    # For NGINX
    # nginx.ingress.kubernetes.io/ssl-redirect: "true"

  hosts:
    - host: ai.yourcompany.com
      paths:
        - path: /
          pathType: Prefix

  tls:
    - secretName: anysource-tls
      hosts:
        - ai.yourcompany.com

Monitoring cert-manager

# Check cert-manager pods
kubectl get pods -n cert-manager

# Check certificate status
kubectl get certificates -n anysource
kubectl describe certificate anysource-tls -n anysource

# Check certificate requests
kubectl get certificaterequests -n anysource

# Check cluster issuer status
kubectl describe clusterissuer letsencrypt-prod

# View cert-manager logs
kubectl logs -n cert-manager deployment/cert-manager

AWS Certificate Manager (ACM)

When to Use ACM

  • AWS-native deployments with ALB/ELB
  • Minimal operational overhead with managed certificates
  • Enterprise compliance requirements
  • Integration with other AWS services

ACM with Application Load Balancer

1

Request Certificate in ACM

# Request certificate via AWS CLI
aws acm request-certificate \
  --domain-name ai.yourcompany.com \
  --subject-alternative-names "*.yourcompany.com" \
  --validation-method DNS \
  --region us-east-1

# Note the certificate ARN for later use
export CERT_ARN="arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
2

Validate Certificate

# Get DNS validation records
aws acm describe-certificate \
  --certificate-arn $CERT_ARN \
  --query 'Certificate.DomainValidationOptions'

# Add CNAME records to your DNS provider
# Certificate will be issued automatically once DNS records are verified
3

Configure ALB Ingress

# values-acm.yaml
ingress:
  enabled: true
  className: "alb"
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    # Use your ACM certificate
    alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-east-1:123456789012:certificate/your-cert-arn"
    alb.ingress.kubernetes.io/ssl-redirect: '443'
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01

  hosts:
    - host: ai.yourcompany.com
      paths:
        - path: /
          pathType: Prefix

  # No TLS section needed - ACM handles certificates

ACM with Terraform

# terraform/certificates.tf
resource "aws_acm_certificate" "anysource" {
  domain_name       = var.domain_name
  subject_alternative_names = ["*.${var.domain_name}"]
  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }

  tags = {
    Name = "anysource-${var.environment}"
  }
}

resource "aws_acm_certificate_validation" "anysource" {
  certificate_arn         = aws_acm_certificate.anysource.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

# Route53 DNS validation records
resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.anysource.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.main.zone_id
}
When using the ECS Terraform module, set enable_acm_dns_validation = true and provide hosted_zone_name (the Route53 zone that exists in the AWS account running Terraform) to have validation records created automatically. The same setting also creates the customer-facing ALIAS record that points your domain at the ALB. If the certificate is for a subdomain (eks.prod.example.com) but the hosted zone is prod.example.com, the hosted_zone_name must match the zone name rather than the certificate FQDN.

Hybrid Approach: ACM + cert-manager

For complex deployments, you can use both:
# values-hybrid.yaml
ingress:
  enabled: true
  className: "alb"
  annotations:
    # Use ACM for primary production domain
    alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-east-1:123456789012:certificate/prod-cert"
    alb.ingress.kubernetes.io/ssl-redirect: '443'

  hosts:
    - host: ai.yourcompany.com  # ACM certificate
      paths:
        - path: /
          pathType: Prefix

# Separate ingress for development/staging with cert-manager
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: anysource-staging
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    kubernetes.io/ingress.class: nginx
spec:
  tls:
    - secretName: staging-tls
      hosts:
        - staging-ai.yourcompany.com
  rules:
    - host: staging-ai.yourcompany.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: anysource-frontend
                port:
                  number: 80

Certificate Renewal

cert-manager Renewal

# cert-manager automatically renews certificates 30 days before expiration
# Check renewal status
kubectl get certificates -n anysource -o wide

# Force renewal (if needed)
kubectl annotate certificate anysource-tls -n anysource \
  cert-manager.io/issue-temporary-certificate="true" --overwrite

# Check renewal logs
kubectl logs -n cert-manager deployment/cert-manager -f

ACM Renewal

ACM certificates are automatically renewed by AWS:
# Check certificate status
aws acm describe-certificate --certificate-arn $CERT_ARN

# ACM automatically renews certificates 60 days before expiration
# No manual intervention required

Troubleshooting

Certificate stuck in pending:
# Check certificate status
kubectl describe certificate anysource-tls -n anysource

# Check certificate request
kubectl describe certificaterequest -n anysource

# Check challenge status
kubectl get challenges -n anysource -o wide

# Common issues:
# - DNS challenge failing (check Route53 permissions)
# - HTTP challenge failing (check ingress controller)
# - Rate limiting (Let's Encrypt limits)
Debugging DNS-01 challenges:
# Check if DNS record was created
dig _acme-challenge.ai.yourcompany.com TXT

# Verify Route53 hosted zone
aws route53 list-hosted-zones
aws route53 list-resource-record-sets --hosted-zone-id Z123456789

# Check cert-manager webhook logs
kubectl logs -n cert-manager deployment/cert-manager-webhook
Certificate validation failing:
# Check certificate validation status
aws acm describe-certificate --certificate-arn $CERT_ARN \
  --query 'Certificate.DomainValidationOptions'

# Common issues:
# - DNS records not added to correct hosted zone
# - DNS propagation delays (can take 24-48 hours)
# - Domain ownership verification failing
ALB not using certificate:
# Check ALB listeners
aws elbv2 describe-listeners --load-balancer-arn $ALB_ARN

# Verify certificate is attached
kubectl describe ingress anysource -n anysource

# Check ingress controller logs
kubectl logs -n kube-system deployment/aws-load-balancer-controller

Best Practices

Security

  • Use TLS 1.2+: Configure modern TLS policies
  • Strong Cipher Suites: Use secure cipher configurations
  • HSTS Headers: Enable HTTP Strict Transport Security
  • Certificate Monitoring: Monitor certificate expiration dates

Operations

  • Automate DNS validation: Use infrastructure as code for DNS records
  • Monitor certificate health: Set up alerts for certificate issues
  • Backup certificates: Store certificate secrets securely
  • Test certificate renewal: Verify automatic renewal processes

Cost Optimization

  • ACM for AWS services: Free certificates for AWS load balancers
  • cert-manager for flexibility: Free Let’s Encrypt certificates
  • Wildcard certificates: Reduce certificate management overhead
  • Proper certificate scoping: Use appropriate certificate coverage

Deployment Scenarios

AWS Production

Recommended: ACM with ALB
  • Managed certificates
  • Automatic renewal
  • AWS integration
  • Enterprise support

Multi-cloud

Recommended: cert-manager
  • Platform independence
  • Kubernetes native
  • Flexible CA options
  • Full control

Development

Recommended: cert-manager
  • Easy setup
  • Free certificates
  • Quick iteration
  • Local testing

Enterprise

Recommended: Hybrid approach
  • ACM for production
  • cert-manager for staging
  • Private CA integration
  • Compliance requirements
Choose the approach that best fits your infrastructure, operational requirements, and compliance needs. Both solutions provide robust, automatic certificate management for MCP Platform deployments.