Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Istio multi primary single network blueprint #1727

Merged
merged 18 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/blueprints/istio-multi-primary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Istio
---

{%
include-markdown "../../examples/istio-multi-cluster/README.md"
%}
1 change: 1 addition & 0 deletions examples/istio-multi-cluster/0.certs-tool/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
certs
102 changes: 102 additions & 0 deletions examples/istio-multi-cluster/0.certs-tool/Makefile.k8s.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
.SUFFIXES: .csr .pem .conf
.PRECIOUS: %/ca-key.pem %/ca-cert.pem %/cert-chain.pem
.PRECIOUS: %/workload-cert.pem %/key.pem %/workload-cert-chain.pem
.SECONDARY: root-cert.csr root-ca.conf %/cluster-ca.csr %/intermediate.conf

.DEFAULT_GOAL := help

SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))

include $(SELF_DIR)common.mk

#------------------------------------------------------------------------
##help: print this help message
.PHONY: help

help:
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/##//'

#------------------------------------------------------------------------
##fetch-root-ca: fetch root CA and key from a k8s cluster.
.PHONY: fetch-root-ca
rawcluster := $(shell kubectl config current-context)
cluster := $(subst /,-,$(rawcluster))
pwd := $(shell pwd)
export KUBECONFIG

fetch-root-ca:
@echo "fetching root ca from k8s cluster: "$(cluster)""
@mkdir -p $(pwd)/$(cluster)
@res=$(shell kubectl get secret istio-ca-secret -n $(ISTIO-NAMESPACE) >/dev/null 2>&1; echo $$?)
ifeq ($(res), 1)
@kubectl get secret cacerts -n $(ISTIO_NAMESPACE) -o "jsonpath={.data['ca-cert\.pem']}" | base64 -d > $(cluster)/k8s-root-cert.pem
@kubectl get secret cacerts -n $(ISTIO_NAMESPACE) -o "jsonpath={.data['ca-key\.pem']}" | base64 -d > $(cluster)/k8s-root-key.pem
else
@kubectl get secret istio-ca-secret -n $(ISTIO_NAMESPACE) -o "jsonpath={.data['ca-cert\.pem']}" | base64 -d > $(cluster)/k8s-root-cert.pem
@kubectl get secret istio-ca-secret -n $(ISTIO_NAMESPACE) -o "jsonpath={.data['ca-key\.pem']}" | base64 -d > $(cluster)/k8s-root-key.pem
endif

k8s-root-cert.pem:
@cat $(cluster)/k8s-root-cert.pem > $@

k8s-root-key.pem:
@cat $(cluster)/k8s-root-key.pem > $@
#------------------------------------------------------------------------
##<name>-cacerts: generate intermediate certificates for a cluster or VM with <name> signed with istio root cert from the specified k8s cluster and store them under <name> directory
.PHONY: %-cacerts

%-cacerts: %/cert-chain.pem
@echo "done"

%/cert-chain.pem: %/ca-cert.pem k8s-root-cert.pem
@echo "generating $@"
@cat $^ > $@
@echo "Intermediate certs stored in $(dir $<)"
@cp k8s-root-cert.pem $(dir $<)/root-cert.pem

%/ca-cert.pem: %/cluster-ca.csr k8s-root-key.pem k8s-root-cert.pem
@echo "generating $@"
@openssl x509 -req -days $(INTERMEDIATE_DAYS) \
-CA k8s-root-cert.pem -CAkey k8s-root-key.pem -CAcreateserial\
-extensions req_ext -extfile $(dir $<)/intermediate.conf \
-in $< -out $@

%/cluster-ca.csr: L=$(dir $@)
%/cluster-ca.csr: %/ca-key.pem %/intermediate.conf
@echo "generating $@"
@openssl req -new -config $(L)/intermediate.conf -key $< -out $@

%/ca-key.pem: fetch-root-ca
@echo "generating $@"
@mkdir -p $(dir $@)
@openssl genrsa -out $@ 4096

#------------------------------------------------------------------------
##<namespace>-certs: generate intermediate certificates and sign certificates for a virtual machine connected to the namespace `<namespace> using serviceAccount `$SERVICE_ACCOUNT` using root cert from k8s cluster.
.PHONY: %-certs

%-certs: fetch-root-ca %/workload-cert-chain.pem k8s-root-cert.pem
@echo "done"

%/workload-cert-chain.pem: k8s-root-cert.pem %/ca-cert.pem %/workload-cert.pem
@echo "generating $@"
@cat $^ > $@
@echo "Intermediate and workload certs stored in $(dir $<)"
@cp k8s-root-cert.pem $(dir $@)/root-cert.pem

%/workload-cert.pem: %/workload.csr
@echo "generating $@"
@openssl x509 -req -days $(WORKLOAD_DAYS) \
-CA $(dir $<)/ca-cert.pem -CAkey $(dir $<)/ca-key.pem -CAcreateserial\
-extensions req_ext -extfile $(dir $<)/workload.conf \
-in $< -out $@

%/workload.csr: L=$(dir $@)
%/workload.csr: %/key.pem %/workload.conf
@echo "generating $@"
@openssl req -new -config $(L)/workload.conf -key $< -out $@

%/key.pem:
@echo "generating $@"
@mkdir -p $(dir $@)
@openssl genrsa -out $@ 4096
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.SUFFIXES: .csr .pem .conf
.PRECIOUS: %/ca-key.pem %/ca-cert.pem %/cert-chain.pem
.PRECIOUS: %/workload-cert.pem %/key.pem %/workload-cert-chain.pem
.SECONDARY: root-cert.csr root-ca.conf %/cluster-ca.csr %/intermediate.conf

.DEFAULT_GOAL := help

SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))

include $(SELF_DIR)common.mk

#------------------------------------------------------------------------
##help: print this help message
.PHONY: help

help:
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/##//'

#------------------------------------------------------------------------
##root-ca: generate root CA files (key and certificate) in current directory.
.PHONY: root-ca

root-ca: root-key.pem root-cert.pem

root-cert.pem: root-cert.csr root-key.pem
@echo "generating $@"
@openssl x509 -req -sha256 -days $(ROOTCA_DAYS) -signkey root-key.pem \
-extensions req_ext -extfile root-ca.conf \
-in $< -out $@

root-cert.csr: root-key.pem root-ca.conf
@echo "generating $@"
@openssl req -sha256 -new -key $< -config root-ca.conf -out $@

root-key.pem:
@echo "generating $@"
@openssl genrsa -out $@ 4096
#------------------------------------------------------------------------
##<name>-cacerts: generate self signed intermediate certificates for <name> and store them under <name> directory.
.PHONY: %-cacerts

%-cacerts: %/cert-chain.pem
@echo "done"

%/cert-chain.pem: %/ca-cert.pem root-cert.pem
@echo "generating $@"
@cat $^ > $@
@echo "Intermediate inputs stored in $(dir $<)"
@cp root-cert.pem $(dir $<)


%/ca-cert.pem: %/cluster-ca.csr root-key.pem root-cert.pem
@echo "generating $@"
@openssl x509 -req -sha256 -days $(INTERMEDIATE_DAYS) \
-CA root-cert.pem -CAkey root-key.pem -CAcreateserial\
-extensions req_ext -extfile $(dir $<)/intermediate.conf \
-in $< -out $@

%/cluster-ca.csr: L=$(dir $@)
%/cluster-ca.csr: %/ca-key.pem %/intermediate.conf
@echo "generating $@"
@openssl req -sha256 -new -config $(L)/intermediate.conf -key $< -out $@

%/ca-key.pem:
@echo "generating $@"
@mkdir -p $(dir $@)
@openssl genrsa -out $@ 4096

#------------------------------------------------------------------------
##<namespace>-certs: generate intermediate certificates and sign certificates for a virtual machine connected to the namespace `<namespace> using serviceAccount `$SERVICE_ACCOUNT` using self signed root certs.
.PHONY: %-certs

%-certs: %/ca-cert.pem %/workload-cert-chain.pem root-cert.pem
@echo "done"

%/workload-cert-chain.pem: %/workload-cert.pem %/ca-cert.pem root-cert.pem
@echo "generating $@"
@cat $^ > $@
@echo "Intermediate and workload certs stored in $(dir $<)"
@cp root-cert.pem $(dir $@)/root-cert.pem


%/workload-cert.pem: %/workload.csr
@echo "generating $@"
@openssl x509 -sha256 -req -days $(WORKLOAD_DAYS) \
-CA $(dir $<)/ca-cert.pem -CAkey $(dir $<)/ca-key.pem -CAcreateserial\
-extensions req_ext -extfile $(dir $<)/workload.conf \
-in $< -out $@

%/workload.csr: L=$(dir $@)
%/workload.csr: %/key.pem %/workload.conf
@echo "generating $@"
@openssl req -sha256 -new -config $(L)/workload.conf -key $< -out $@

%/key.pem:
@echo "generating $@"
@mkdir -p $(dir $@)
@openssl genrsa -out $@ 4096
26 changes: 26 additions & 0 deletions examples/istio-multi-cluster/0.certs-tool/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generating Certificates for Bootstrapping Multicluster / Mesh Expansion Chain of Trust

The directory contains two Makefiles for generating new root, intermediate certificates and workload certificates:
- `Makefile.k8s.mk`: Creates certificates based on a root-ca from a k8s cluster. The current context in the default
`kubeconfig` is used for accessing the cluster.
- `Makefile.selfsigned.mk`: Creates certificates based on a generated self-signed root.
rodrigobersa marked this conversation as resolved.
Show resolved Hide resolved

The table below describes the targets supported by both Makefiles.

Make Target | Makefile | Description
------ | -------- | -----------
`root-ca` | `Makefile.selfsigned.mk` | Generates a self-signed root CA key and certificate.
`fetch-root-ca` | `Makefile.k8s.mk` | Fetches the Istio CA from the Kubernetes cluster, using the current context in the default `kubeconfig`.
`$NAME-cacerts` | Both | Generates intermediate certificates signed by the root CA for a cluster or VM with `$NAME` (e.g., `us-east`, `cluster01`, etc.). They are stored under `$NAME` directory. To differentiate between clusters, we include a `Location` (`L`) designation in the certificates `Subject` field, with the cluster's name.
`$NAMESPACE-certs` | Both | Generates intermediate certificates and sign certificates for a virtual machine connected to the namespace `$NAMESPACE` using serviceAccount `$SERVICE_ACCOUNT` using the root cert and store them under `$NAMESPACE` directory.
`clean` | Both | Removes any generated root certificates, keys, and intermediate files.

For example:

```bash
make -f Makefile.selfsigned.mk root-ca
```

Note that the Makefile generates long-lived intermediate certificates. While this might be
acceptable for demonstration purposes, a more realistic and secure deployment would use
short-lived and automatically renewed certificates for the intermediate CAs.
101 changes: 101 additions & 0 deletions examples/istio-multi-cluster/0.certs-tool/common.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#------------------------------------------------------------------------
# variables: root CA
ROOTCA_DAYS ?= 3650
ROOTCA_KEYSZ ?= 4096
ROOTCA_ORG ?= Istio
ROOTCA_CN ?= Root CA
KUBECONFIG ?= $(HOME)/.kube/config
ISTIO_NAMESPACE ?= istio-system
# Additional variables are defined in root-ca.conf target below.

#------------------------------------------------------------------------
# variables: intermediate CA
INTERMEDIATE_DAYS ?= 3650
INTERMEDIATE_KEYSZ ?= 4096
INTERMEDIATE_ORG ?= Istio
INTERMEDIATE_CN ?= Intermediate CA
INTERMEDIATE_SAN_DNS ?= istiod.istio-system.svc
# Additional variables are defined in %/intermediate.conf target below.

#------------------------------------------------------------------------
# variables: workload certs: eg VM
WORKLOAD_DAYS ?= 1
SERVICE_ACCOUNT ?= default
WORKLOAD_CN ?= Workload

#------------------------------------------------------------------------
# variables: files to clean
FILES_TO_CLEAN+=k8s-root-cert.pem \
k8s-root-cert.srl \
k8s-root-key.pem root-ca.conf root-cert.csr root-cert.pem root-cert.srl root-key.pem
#------------------------------------------------------------------------
# clean
.PHONY: clean

clean: ## Cleans all the intermediate files and folders previously generated.
@rm -f $(FILES_TO_CLEAN)

root-ca.conf:
@echo "[ req ]" > $@
@echo "encrypt_key = no" >> $@
@echo "prompt = no" >> $@
@echo "utf8 = yes" >> $@
@echo "default_md = sha256" >> $@
@echo "default_bits = $(ROOTCA_KEYSZ)" >> $@
@echo "req_extensions = req_ext" >> $@
@echo "x509_extensions = req_ext" >> $@
@echo "distinguished_name = req_dn" >> $@
@echo "[ req_ext ]" >> $@
@echo "subjectKeyIdentifier = hash" >> $@
@echo "basicConstraints = critical, CA:true" >> $@
@echo "keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, keyCertSign" >> $@
@echo "[ req_dn ]" >> $@
@echo "O = $(ROOTCA_ORG)" >> $@
@echo "CN = $(ROOTCA_CN)" >> $@

%/intermediate.conf: L=$(dir $@)
%/intermediate.conf:
@echo "[ req ]" > $@
@echo "encrypt_key = no" >> $@
@echo "prompt = no" >> $@
@echo "utf8 = yes" >> $@
@echo "default_md = sha256" >> $@
@echo "default_bits = $(INTERMEDIATE_KEYSZ)" >> $@
@echo "req_extensions = req_ext" >> $@
@echo "x509_extensions = req_ext" >> $@
@echo "distinguished_name = req_dn" >> $@
@echo "[ req_ext ]" >> $@
@echo "subjectKeyIdentifier = hash" >> $@
@echo "basicConstraints = critical, CA:true, pathlen:0" >> $@
@echo "keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, keyCertSign" >> $@
@echo "subjectAltName=@san" >> $@
@echo "[ san ]" >> $@
@echo "DNS.1 = $(INTERMEDIATE_SAN_DNS)" >> $@
@echo "[ req_dn ]" >> $@
@echo "O = $(INTERMEDIATE_ORG)" >> $@
@echo "CN = $(INTERMEDIATE_CN)" >> $@
@echo "L = $(L:/=)" >> $@

%/workload.conf: L=$(dir $@)
%/workload.conf:
@echo "[ req ]" > $@
@echo "encrypt_key = no" >> $@
@echo "prompt = no" >> $@
@echo "utf8 = yes" >> $@
@echo "default_md = sha256" >> $@
@echo "default_bits = $(INTERMEDIATE_KEYSZ)" >> $@
@echo "req_extensions = req_ext" >> $@
@echo "x509_extensions = req_ext" >> $@
@echo "distinguished_name = req_dn" >> $@
@echo "[ req_ext ]" >> $@
@echo "subjectKeyIdentifier = hash" >> $@
@echo "basicConstraints = critical, CA:false" >> $@
@echo "keyUsage = digitalSignature, keyEncipherment" >> $@
@echo "extendedKeyUsage = serverAuth, clientAuth" >> $@
@echo "subjectAltName=@san" >> $@
@echo "[ san ]" >> $@
@echo "URI.1 = spiffe://cluster.local/ns/$(L)sa/$(SERVICE_ACCOUNT)" >> $@
@echo "[ req_dn ]" >> $@
@echo "O = $(INTERMEDIATE_ORG)" >> $@
@echo "CN = $(WORKLOAD_CN)" >> $@
@echo "L = $(L:/=)" >> $@
6 changes: 6 additions & 0 deletions examples/istio-multi-cluster/0.certs-tool/create-certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# https://istio.io/latest/docs/tasks/security/cert-management/plugin-ca-cert/#plug-in-certificates-and-key-into-the-cluster
mkdir certs
cd certs
make -f ../Makefile.selfsigned.mk root-ca
make -f ../Makefile.selfsigned.mk cluster-1-cacerts
make -f ../Makefile.selfsigned.mk cluster-2-cacerts
Loading