惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
Last Week in AI
Last Week in AI
MongoDB | Blog
MongoDB | Blog
T
Tailwind CSS Blog
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
腾讯CDC
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
N
News | PayPal Newsroom
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
Apple Machine Learning Research
Apple Machine Learning Research
雷峰网
雷峰网
A
Arctic Wolf
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
Cyber Attacks, Cyber Crime and Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
AI
AI
S
Security @ Cisco Blogs
aimingoo的专栏
aimingoo的专栏
Cloudbric
Cloudbric
爱范儿
爱范儿
罗磊的独立博客
Y
Y Combinator Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
Webroot Blog
Webroot Blog
T
Threatpost
T
Threat Research - Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
Security Latest
Security Latest
P
Proofpoint News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
I
Intezer
H
Heimdal Security Blog
Blog — PlanetScale
Blog — PlanetScale
S
Securelist
Forbes - Security
Forbes - Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Learn Cloud Native

Agentgateway rate limiting for agents | Learn Cloud Native Local development with coding agents on Kubernetes using Signadot | Learn Cloud Native cuenv: one typed file for your whole project | Learn Cloud Native Preflight: AI Code Review Before You Push Anatomy of AI Agents Accessing Google Drive from Next.js Deploying to Fly.io using Dagger and Github Top Cloud-Native & Kubernetes Certifications [2026 Guide] Rapid microservices development with Signadot How to prepare for Istio certified associate exam (ICA) Global Rate Limiting in Istio with Envoy Rate Limit Service My Journey with Istio: From Incubation to Graduation Cilium Network Policy Tutorial: Secure Kubernetes Step by Step Kubernetes Networking: How kube-proxy and iptables Work Istio ServiceEntry: DNS vs. STATIC Resolution & Endpoints Explained Apply an Istio DestinationRule Globally (Mesh-Wide) Istio Rate Limiting: Configure a Local Rate Limiter in Envoy How to expose custom ports on Istio ingress gateway Portainer Tutorial: A Web UI for Kubernetes & Containers Traefik Proxy 2.x and TLS 101 Kubernetes CLI (kubectl) tips you didn't know about ArgoCD Best Practices You Should Know 在 OCI Ampere A1 计算实例上运行 AI Running AI On OCI Ampere A1 Instance How to Deploy Traefik Proxy Using Flux and GitOps Principles Firebase Emulators with Next.js: Local Setup Guide Running Hugo on free Ampere VM (Oracle Cloud Infrastructure) How to use kwatch to detect crashes in Kubernetes clusters Continuous profiling in Kubernetes using Pyroscope Monitoring containers with cAdvisor Creating a Kubernetes cluster in Google Cloud (LAB) Your first Kubernetes Pod and ReplicaSet (LABS) Container Lifecycle Hooks Maybe Convert Wasm Extension Config? GetIstio - CLI, training, and community Attach multiple VirtualServices to Istio Gateway Kubernetes Volumes Explained: Keep Data Beyond the Pod Send a Slack message when Docker images are updated Kubernetes Network Policy Ambassador Container Pattern Start Kubernetes Release Sidecar Container Pattern Kubernetes Init Containers Deploying multiple Istio Ingress Gateways Branch by Abstraction Pattern The Strangler Pattern Kubernetes Development Environment with Skaffold Securing Kubernetes Ingress with Ambassador and Let's Encrypt All About the Ingress Resource How to quarantine Kubernetes pods? Getting started with Kubernetes Horizontal partitioning in MongoDB Docker image tagging scheme Six things to keep in mind when working with Dockerfiles Beginners guide to Docker Beginners guide to gateways and proxies Deploy and Operate Multiple Istio Meshes in one Kubernetes Cluster Managing service meshes with Meshery Circuit Breaking in Istio Explained Build and push your Docker images using Github Actions Kubernetes and Istio service mesh workshop materials Build Netlify-like deployment for React app using Kubernetes pods Six exciting enhancements in Istio 1.4.0 Fallacies of Distributed Systems CAP Theorem Explained Master the Kubernetes CLI (kubectl) - Cheatsheet Minikube Basics and How to Get Started with Kubernetes 5 Tips to Be More Productive with Kubernetes What are sticky sessions and how to configure them with Istio? Debugging Kubernetes applications using Istio Kubernetes Ingress and Istio Gateway Resource Zero Downtime Releases using Kubernetes and Istio Traffic Mirroring with Istio Service Mesh Expose a Kubernetes service on your own custom domain
Setting up SSL certificates with Istio Gateway
Peter Jausovec · 2022-05-05 · via Learn Cloud Native

SSL certificates are a must these days. They help protect the data being sent between the server and the client by encrypting it, which gives your website more credibility. In this blog post, I will explore a couple of different ways you can obtain SSL certificates and configure the Istio Gateway to use them.

In this first part, I will show you how to create a self-signed certificate manually, then obtain an actual SSL certificate and set that up. As you will see, setting all this up is not too complicated. In one of the future posts, I also explain how to retrieve and refresh the certificates before they expire automatically.

You will need an actual, cloud-hosted Kubernetes cluster to follow along because you will need an external IP address you can hook up your domain to. I've tested the steps using the demo profile installation of Istio 1.13.3.

Prerequisites:

  • Cloud-hosted Kubernetes cluster
  • Istio 1.13.3 (e.g. istioctl install) with default namespace labelled for Istio sidecar injection

Deploying a sample application

To ensure stuff works, we'll start by deploying a simple Hello World web application. If you have your own application/service you want to use, feel free to use that.

Let's define the Kubernetes service account, service, and deployment:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: helloworld
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  labels:
    app: helloworld
    service: helloworld
spec:
  ports:
    - name: http
      port: 80
      targetPort: 3000
  selector:
    app: helloworld
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v1
  template:
    metadata:
      labels:
        app: helloworld
        version: v1
    spec:
      serviceAccountName: helloworld
      containers:
        - image: learncloudnative/helloworld:0.1.0
          imagePullPolicy: IfNotPresent
          name: helloworld
          ports:
            - containerPort: 3000

Save the above file to helloworld.yaml and deploy it using kubectl apply -f helloworld.yaml.

Since we'll be exposing the helloworld application on a public domain, we'll need to create a Gateway resource:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: public-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - '*'

Save above to gateway.yaml and deploy it using kubectl apply -f gateway.yaml.

Note

Check out the Tweet below that explains what * in the hosts field means and how the Gateway resource relates to the VirtualService.

We also need a VirtualService that attaches to the Gateway resource and routes the traffic to the helloworld Kubernetes service:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - '*'
  gateways:
    - public-gateway
  http:
    - route:
        - destination:
            host: helloworld.default.svc.cluster.local
            port:
              number: 80

Save the above YAML to virtualservice.yaml and deploy it using kubectl apply -f virtualservice.yaml.

We can list the VirtualService to see which Gateway it is attached to and which hosts it listens for:

NAME         GATEWAYS             HOSTS   AGE
helloworld   ["public-gateway"]   ["*"]   106s

With all these resources deployed, we can now get the external IP of the Istio's ingress gateway and store it in the GATEWAY_URL environment variable:

GATEWAY_IP=$(kubectl get svc -n istio-system istio-ingressgateway -ojsonpath='{.status.loadBalancer.ingress[0].ip}')

If you open the GATEWAY_IP in the browser, you will see something similar to the figure below.

Connection not secure
Connection not secure

You did get a response back from the application, but you also got the Not Secure message from the browser, which tells the user that the connection is not secure and doesn't instill confidence in your website.

Self-signed certs and manual setup

Let's start with the simplest scenario where we manually obtain the certificates. First thing - pick a domain you want to use - note that to test this, you don't have to own the domain name:

export DOMAIN_NAME=mysuperdomain.com

As a first step, you are going to create the root certificate ($DOMAIN_NAME.crt) and the private key used for signing the certificate ($DOMAIN_NAME.key):

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=$DOMAIN_NAME Inc./CN=$DOMAIN_NAME' -keyout $DOMAIN_NAME.key -out $DOMAIN_NAME.crt

Next, you need to create the private key:

openssl req -out helloworld.$DOMAIN_NAME.csr -newkey rsa:2048 -nodes -keyout helloworld.$DOMAIN_NAME.key -subj "/CN=helloworld.$DOMAIN_NAME/O=hello world from $DOMAIN_NAME"
Generating a 2048 bit RSA private key
....................................+++
..............................................+++
writing new private key to 'helloworld.mysuperdomain.com.key'

And the certificate:

openssl x509 -req -days 365 -CA $DOMAIN_NAME.crt -CAkey $DOMAIN_NAME.key -set_serial 0 -in helloworld.$DOMAIN_NAME.csr -out helloworld.$DOMAIN_NAME.crt
Signature ok
subject=/CN=helloworld.mysuperdomain.com/O=hello world from mysuperdomain.com
Getting CA Private Key

Once you run the commands above, you'll end up with the following files:

.
  |-mysuperdomain.com.key
  |-helloworld.mysuperdomain.com.csr
  |-helloworld.mysuperdomain.com.crt
  |-mysuperdomain.com.crt
  |-helloworld.mysuperdomain.com.key

We can create the Kubernetes secret to store the certificate and the key. We can call the secret whatever we want, as long as we put it in the same namespace as the ingress gateway is running it. By default, this is the istio-system namespace.

kubectl create secret tls mysuperdomain-certs -n istio-system --key helloworld.$DOMAIN_NAME.key --cert helloworld.$DOMAIN_NAME.crt
secret/mysuperdomain-certs created

With the secret in place, we need to update the Gateway resource to tell it to use this certificate:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: public-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: mysuperdomain-certs
      hosts:
        - helloworld.mysuperdomain.com

Save the above YAML to gateway.yaml and deploy it using kubectl apply -f gateway.yaml. We'll overwrite the previous Gateway resource we created using the apply command.

Similarly, we need to update the hosts field in the VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - helloworld.mysuperdomain.com
  gateways:
    - public-gateway
  http:
    - route:
        - destination:
            host: helloworld.default.svc.cluster.local
            port:
              number: 80

Save the above YAML to virtualservice.yaml and overwrite the existing VirtualService using kubectl apply -f virtualservice.yaml.

The simplest way to test this works is to use curl with the --resolve flag. The resolve flag has a format of [DOMAIN]:[PORT]:[IP] and it routes all requests that match the [DOMAIN]:[PORT] portion to the specified IP address. This way, you don't need to go to your DNS/domain registrar and make changes there to be able to test this.

Here's the curl command you can use to test that the SSL certs get verified and used:

curl -v --resolve helloworld.$DOMAIN_NAME:443:$GATEWAY_IP --cacert $DOMAIN_NAME.crt https://helloworld.$DOMAIN_NAME

With the above command, we are telling curl to resolve any requests to helloworld.mysuperdomain.com:443 to the external IP address of the ingress gateway. Additionally, we provide the name of the CA certificate we created earlier.

From the output, you will be able to see the details of the server certificate and a line that says the certificate was verified as well as the actual response from the helloworld pod:

...
* Server certificate:
*  subject: CN=helloworld.mysuperdomain.com; O=hello world from mysuperdomain.com
*  start date: Nov 30 22:27:11 2019 GMT
*  expire date: Nov 29 22:27:11 2020 GMT
*  common name: helloworld.mysuperdomain.com (matched)
*  issuer: O=mysuperdomain.com Inc.; CN=mysuperdomain.com
*  SSL certificate verify ok.
...

<link rel="stylesheet" type="text/css" href="css/style.css" />

<div class="container">
    Hello World!
* Connection #0 to host helloworld.mysuperdomain.com left intact
</div>* Closing connection 0

Using ZeroSSL to get the certificates

The self-signed cert route from the previous section is practical only to kick the tires and test things out. However, you'll need certificates signed by an actual certificate authority that your clients can trust.

There are a couple of ways to get the SSL certificates, the most popular one being Let's Encrypt. I'll use ZeroSSL, which uses Let's Encrypt to issue the certificates. If you want to spend money, you can also purchase SSL certificates from your domain registrar or at DigiCert.

In this section, I'll use a real domain name and actual SSL certificates - this means that if you want to follow along, make sure you have your name domain ready to go. I am using Name.com, but you can use any other domain registrar.

Now that you have your domain, register, and login to ZeroSSL to get your SSL certificates:

  1. Click the New Certificate button to get started.
  2. Enter the domain name and click the Next Step button. I'll use startcloudnative.com for my domain name
  3. Select the 90-Day Certificate and click the Next Step button.
  4. Select the Free option and click Next Step button.

Before you can download the certificate and the key, you'll have to verify that you own the domain name you requested the certificate for. There are multiple options to verify the domain name ownership. If you have an email set up on the domain, you can pick the Email Verification; otherwise use the DNS (CNAME) verification.

The DNS verification will require you to log in to the website where you registered your domain and add a custom DNS record. Once you've done that, click the Next Step button and the Verify Domain button.

Installing the SSL cert
Installing the SSL cert

Set the A name record

While you are logged in to the domain registrar's website, make sure you add an A record. The A record (IP address) will point your domain to the external IP address of the Istio ingress gateway (the GATEWAY_IP).

I've requested a certificate for startcloudnative.com and www.startcloudnative.com. My A record will point from startcloudnative.com to the IP address (the GATEWAY_IP). I won't use the helloworld subdomain as we did previously.

Once the certificates are issued, you can download the .zip file with all generated files for your domain. You have an option of picking multiple server types, but leaving it on Default Format is what we want.

There will be three files in the .zip package:

  • ca_bundle.crt
  • certificate.crt
  • private.key

Re-creating the secret with a real certificate

Let's delete the last secret we created and create a new one with the actual certificates:

kubectl delete mysuperdomain-certs -n istio-system

You can re-create it with the actual SSL certificate and key you got from the downloaded package. You can name the secret using your domain name:

kubectl create secret tls startcloudnative-certs -n istio-system --key private.key --cert certificate.crt
secret/startcloudnative-certs created

We also have to update the Gateway and the VirtualService to modify the hostnames and point to the new secret we created.

Let's update the Gateway first (make sure you replace the startcloudnative.com with your actual domain name):

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: public-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: startcloudnative-certs
      hosts:
        - startcloudnative.com

Similarly, let's make a change to the hosts field in the VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - startcloudnative.com
  gateways:
    - public-gateway
  http:
    - route:
        - destination:
            host: helloworld.default.svc.cluster.local
            port:
              number: 80

With both of these resources updated, you can open your browser of choice and navigate to your domain. You should see the Hello World! response and the padlock before the domain name, which signifies that the website is secure. If you click on the padlock and check the certificate, you will see your domain name in the certificate, the root authority (Let's Encrypt), and the expiration date.

SSL secured site
SSL secured site

Conclusion

This article explained how to configure the Istio ingress gateway to serve HTTPS traffic. We also covered creating self-signed TLS certificates and using the ZeroSSL to create an actual SSL certificate.