Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Add a certificate rotation command #1435

Merged
merged 18 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ run-e2e-tests:
KUBECONFIG=${kubeconfig} PLATFORM=${platform} go test -mod=$(MOD) -tags="$(platform),poste2e" -covermode=atomic -buildmode=exe -v -count=1 -timeout=17m ./test/...
# This is a test that should be run in the end to reduce the disruption to other tests because
# it will delete a node.
KUBECONFIG=${kubeconfig} PLATFORM=${platform} go test -mod=$(MOD) -tags="$(platform),disruptivee2e" -covermode=atomic -buildmode=exe -v -count=1 ./test/...
# The timeout is made longer as it will perform actions that will take longer than the default 10 minutes.
KUBECONFIG=${kubeconfig} PLATFORM=${platform} go test -timeout 30m -mod=$(MOD) -tags="$(platform),disruptivee2e" -covermode=atomic -buildmode=exe -v -count=1 ./test/...

.PHONY: all
all: build test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ spec:
annotations:
checkpointer.alpha.coreos.com/checkpoint: "true"
seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
# Automatically rolls update when secret changes.
checksum/secret: {{ include (print $.Template.BasePath "/kube-apiserver-secret.yaml") . | sha256sum }}
spec:
{{- template "containers" . }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ spec:
annotations:
checkpointer.alpha.coreos.com/checkpoint: "true"
seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
# Automatically rolls update when secret changes.
checksum/secret: {{ include (print $.Template.BasePath "/kube-apiserver-secret.yaml") . | sha256sum }}
spec:
{{- template "containers" . }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
FROM quay.io/poseidon/kubelet:v1.20.4

RUN clean-install \
sed \
bash

COPY ./iscsiadm /bin/iscsiadm
2 changes: 2 additions & 0 deletions assets/charts/control-plane/kubelet/container-image/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This image is built on top of the Typhoon Kubelet image. This image includes a wrapper script that runs `isciadm` in the host namespace. This ensures that all the `isciadm` libraries are loaded from the host.

We also use `sed` and `bash` of the image to run the `ca-syncer` init container.

## Updating Image Tag

In this directory run the following command to update the Kubernetes version:
Expand Down
16 changes: 15 additions & 1 deletion assets/charts/control-plane/kubelet/templates/kubelet-ds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,21 @@ spec:
tier: node
k8s-app: kubelet
spec:
automountServiceAccountToken: false
initContainers:
- name: ca-syncer
image: {{ .Values.image }}
command:
- bash
- -c
- |
sed -i "s/^ certificate-authority-data:.*$/ certificate-authority-data: {{ required "kubernetesCACert can't be empty" .Values.kubernetesCACert }}/g" /var/lib/kubelet/kubeconfig /etc/kubernetes/kubeconfig
volumeMounts:
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: false
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: false
containers:
- name: kubelet
image: {{ .Values.image }}
Expand Down
1 change: 1 addition & 0 deletions assets/charts/control-plane/kubelet/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ clusterDNS: 10.0.0.10
clusterDomain: cluster.local
enableTLSBootstrap: true
cloudProvider:
kubernetesCACert: ""
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ spec:
k8s-app: kube-controller-manager
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
# Automatically rolls update when secret changes.
checksum/secret: {{ include (print $.Template.BasePath "/kube-controller-manager-secret.yaml") . | sha256sum }}
spec:
{{- template "controller-manager-containers" . }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ spec:
k8s-app: kube-controller-manager
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
# Automatically rolls update when secret changes.
checksum/secret: {{ include (print $.Template.BasePath "/kube-controller-manager-secret.yaml") . | sha256sum }}
spec:
{{- template "controller-manager-containers" . }}
{{- end }}
12 changes: 10 additions & 2 deletions assets/terraform-modules/aws/flatcar-linux/kubernetes/ssh.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ resource "null_resource" "copy-controller-secrets" {

provisioner "remote-exec" {
inline = [
"set -e",
"sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig",
"sudo chown root:root /etc/kubernetes/kubeconfig",
"sudo chmod 644 /etc/kubernetes/kubeconfig",
"sudo chmod 600 /etc/kubernetes/kubeconfig",
# Using "etcd/." copies the etcd/ folder recursively in an idempotent
# way. See https://unix.stackexchange.com/a/228637 for details.
"[ -d /etc/ssl/etcd ] && sudo cp -R /etc/ssl/etcd/. /etc/ssl/etcd.old && sudo rm -rf /etc/ssl/etcd",
"sudo mkdir -p /etc/ssl/etcd/etcd",
"sudo mv etcd-client* /etc/ssl/etcd/",
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt",
Expand All @@ -70,11 +74,15 @@ resource "null_resource" "copy-controller-secrets" {
"sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key",
"sudo chown -R etcd:etcd /etc/ssl/etcd",
"sudo chmod -R 500 /etc/ssl/etcd",
"sudo systemctl restart etcd",
]
}

triggers = {
controller_id = aws_instance.controllers[count.index].id
controller_id = aws_instance.controllers[count.index].id
etcd_ca_cert = module.bootkube.etcd_ca_cert
etcd_server_cert = module.bootkube.etcd_server_cert
etcd_peer_cert = module.bootkube.etcd_peer_cert
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ resource "null_resource" "copy-controller-secrets" {

provisioner "remote-exec" {
inline = [
"set -e",
"sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig",
"sudo chown root:root /etc/kubernetes/kubeconfig",
"sudo chmod 600 /etc/kubernetes/kubeconfig",
# Using "etcd/." copies the etcd/ folder recursively in an idempotent
# way. See https://unix.stackexchange.com/a/228637 for details.
"[ -d /etc/ssl/etcd ] && sudo cp -R /etc/ssl/etcd/. /etc/ssl/etcd.old && sudo rm -rf /etc/ssl/etcd",
"sudo mkdir -p /etc/ssl/etcd/etcd",
"sudo mv etcd-client* /etc/ssl/etcd/",
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt",
Expand All @@ -74,9 +81,15 @@ resource "null_resource" "copy-controller-secrets" {
"sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key",
"sudo chown -R etcd:etcd /etc/ssl/etcd",
"sudo chmod -R 500 /etc/ssl/etcd",
"sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig",
"sudo systemctl restart etcd",
Comment on lines -77 to +84
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can commit etcd related changes and kubelet changes separately, so diff is clearer? Some context why this is needed would be nice too :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will split.

]
}

triggers = {
etcd_ca_cert = module.bootkube.etcd_ca_cert
etcd_server_cert = module.bootkube.etcd_server_cert
etcd_peer_cert = module.bootkube.etcd_peer_cert
}
}

# Secure copy kubeconfig to all workers. Activates kubelet.service
Expand Down
1 change: 1 addition & 0 deletions assets/terraform-modules/bootkube/assets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ locals {
cluster_domain_suffix = var.cluster_domain_suffix
enable_tls_bootstrap = var.enable_tls_bootstrap
cloud_provider = var.cloud_provider
kubernetes_ca_cert = base64encode(tls_self_signed_cert.kube-ca.cert_pem)
})

kubeconfig_kubelet_content = templatefile("${path.module}/resources/kubeconfig-kubelet", {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ clusterDNS: ${cluster_dns_service_ip}
clusterDomain: ${cluster_domain_suffix}
enableTLSBootstrap: ${enable_tls_bootstrap}
cloudProvider: ${cloud_provider}
kubernetesCACert: ${kubernetes_ca_cert}
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,18 @@ output "calico_values" {
value = module.bootkube.calico_values
}

output "calico-host-protection_values" {
value = local_file.calico_host_protection.content
}

output "lokomotive_values" {
value = module.bootkube.lokomotive_values
}

output "packet-ccm_values" {
value = local_file.packet-ccm.content
}

output "bootstrap-secrets_values" {
value = module.bootkube.bootstrap-secrets_values
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ resource "null_resource" "copy-controller-secrets" {

provisioner "remote-exec" {
inline = [
"set -e",
# Using "etcd/." copies the etcd/ folder recursively in an idempotent
# way. See https://unix.stackexchange.com/a/228637 for details.
"[ -d /etc/ssl/etcd ] && sudo cp -R /etc/ssl/etcd/. /etc/ssl/etcd.old && sudo rm -rf /etc/ssl/etcd",
"sudo mkdir -p /etc/ssl/etcd/etcd",
"sudo mv etcd-client* /etc/ssl/etcd/",
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt",
Expand All @@ -56,11 +60,14 @@ resource "null_resource" "copy-controller-secrets" {
"sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key",
"sudo chown -R etcd:etcd /etc/ssl/etcd",
"sudo chmod -R 500 /etc/ssl/etcd",
"sudo systemctl restart etcd",
]
}

triggers = {
controller_id = packet_device.controllers[count.index].id
etcd_ca_cert = module.bootkube.etcd_ca_cert
etcd_server_cert = module.bootkube.etcd_server_cert
etcd_peer_cert = module.bootkube.etcd_peer_cert
}
}

Expand Down
15 changes: 14 additions & 1 deletion assets/terraform-modules/platforms/tinkerbell/controllers/ssh.tf
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ resource "null_resource" "copy-controller-secrets" {

provisioner "remote-exec" {
inline = [
"set -e",
"sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig",
"sudo chown root:root /etc/kubernetes/kubeconfig",
"sudo chmod 600 /etc/kubernetes/kubeconfig",
# Using "etcd/." copies the etcd/ folder recursively in an idempotent
# way. See https://unix.stackexchange.com/a/228637 for details.
"[ -d /etc/ssl/etcd ] && sudo cp -R /etc/ssl/etcd/. /etc/ssl/etcd.old && sudo rm -rf /etc/ssl/etcd",
"sudo mkdir -p /etc/ssl/etcd/etcd",
"sudo mv etcd-client* /etc/ssl/etcd/",
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt",
Expand All @@ -61,9 +68,15 @@ resource "null_resource" "copy-controller-secrets" {
"sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key",
"sudo chown -R etcd:etcd /etc/ssl/etcd",
"sudo chmod -R 500 /etc/ssl/etcd",
"sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig",
"sudo systemctl restart etcd",
]
}

triggers = {
etcd_ca_cert = module.bootkube.etcd_ca_cert
etcd_server_cert = module.bootkube.etcd_server_cert
etcd_peer_cert = module.bootkube.etcd_peer_cert
}
}

# Secure copy bootkube assets to ONE controller and start bootkube to perform
Expand Down
1 change: 1 addition & 0 deletions ci/scripts/deploy-cluster.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ resource_dir=$(pwd)/..
cd "ci/$platform"
cat "$platform-cluster.lokocfg.envsubst" | envsubst '$AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY $PUB_KEY $CLUSTER_ID $AWS_DEFAULT_REGION $AWS_DNS_ZONE $AWS_DNS_ZONE_ID $PACKET_PROJECT_ID $EMAIL $GITHUB_CLIENT_ID $GITHUB_CLIENT_SECRET $DEX_STATIC_CLIENT_CLUSTERAUTH_ID $DEX_STATIC_CLIENT_CLUSTERAUTH_SECRET $GANGWAY_REDIRECT_URL $GANGWAY_SESSION_KEY $DEX_INGRESS_HOST $GANGWAY_INGRESS_HOST $ISSUER_HOST $REDIRECT_URI $API_SERVER_URL $AUTHORIZE_URL $TOKEN_URL $PACKET_LOCATION $ARM_SUBSCRIPTION_ID $ARM_TENANT_ID $ARM_CLIENT_ID $ARM_CLIENT_SECRET' >"$platform-cluster.lokocfg"

export LOKOCFG_LOCATION="$(pwd)/$platform-cluster.lokocfg"
export KUBECONFIG=$HOME/lokoctl-assets/cluster-assets/auth/kubeconfig
echo "export KUBECONFIG=$KUBECONFIG" >> ~/.bashrc

Expand Down
57 changes: 57 additions & 0 deletions cli/cmd/cluster-certificate-rotate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2021 The Lokomotive Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/kinvolk/lokomotive/cli/cmd/cluster"
)

var clusterCertificateRotateCmd = &cobra.Command{
Use: "rotate",
Short: "Rotate certificates of a cluster",
Long: `Rotate certificates of a cluster.
Rotate will replace all certificates inside a cluster with new ones.
This can be used to renew all certificates with a longer validity.`,
Run: runClusterCertificateRotate,
}

func init() { //nolint:gochecknoinits
clusterCertificateCmd.AddCommand(clusterCertificateRotateCmd)

pf := clusterCertificateRotateCmd.PersistentFlags()
pf.BoolVarP(&verbose, "verbose", "v", false, "Show output from Terraform")
}

func runClusterCertificateRotate(cmd *cobra.Command, args []string) {
contextLogger := log.WithFields(log.Fields{
"command": "lokoctl cluster certificate rotate",
"args": args,
})

options := cluster.CertificateRotateOptions{
Confirm: confirm,
Verbose: verbose,
ConfigPath: viper.GetString("lokocfg"),
ValuesPath: viper.GetString("lokocfg-vars"),
}

if err := cluster.RotateCertificates(contextLogger, options); err != nil {
contextLogger.Fatalf("Rotating Certificates failed: %v", err)
}
}
28 changes: 28 additions & 0 deletions cli/cmd/cluster-certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2021 The Lokomotive Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"github.com/spf13/cobra"
)

var clusterCertificateCmd = &cobra.Command{
Use: "certificate",
Short: "Manage cluster certificates",
}

func init() { //nolint:gochecknoinits
clusterCmd.AddCommand(clusterCertificateCmd)
}
17 changes: 2 additions & 15 deletions cli/cmd/cluster/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,8 @@ func Apply(contextLogger *log.Entry, options ApplyOptions) error {
if exists && !c.platform.Meta().Managed {
fmt.Printf("\nEnsuring that cluster controlplane is up to date.\n")

cu := controlplaneUpdater{
kubeconfig: kubeconfig,
assetDir: c.assetDir,
contextLogger: *contextLogger,
ex: c.terraformExecutor,
}

if err := c.unpackControlplaneCharts(); err != nil {
return fmt.Errorf("unpacking controlplane assets: %w", err)
}

for _, c := range charts {
if err := cu.upgradeComponent(c.Name, c.Namespace); err != nil {
return fmt.Errorf("upgrading controlplane component %q: %w", c.Name, err)
}
if err := c.upgradeControlPlane(contextLogger, kubeconfig); err != nil {
return fmt.Errorf("running controlplane upgrade: %v", err)
}
}

Expand Down
Loading