Add LE renewal pipeline
This commit is contained in:
parent
ac5301f371
commit
463ae3f35f
9 changed files with 135 additions and 7 deletions
39
.drone.yml
39
.drone.yml
|
|
@ -28,3 +28,42 @@ steps:
|
|||
- "git remote set-url origin git@github.com:ViktorBarzin/infra.git"
|
||||
- "git commit -m 'Drone CI deploy commit' || echo 'No changes'"
|
||||
- "GIT_SSH_COMMAND='ssh -i ./secrets/deploy_key -o IdentitiesOnly=yes' git push origin master"
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: renew-tls-certificate
|
||||
trigger:
|
||||
event:
|
||||
- cron
|
||||
cron:
|
||||
- nightly
|
||||
|
||||
steps:
|
||||
- name: Prepare terraform files
|
||||
image: alpine
|
||||
commands:
|
||||
- "apk update && apk add jq curl git git-crypt"
|
||||
- |
|
||||
curl -k https://kubernetes:6443/api/v1/namespaces/drone/configmaps/git-crypt-key -H "Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" | jq -r .data.key | base64 -d > /tmp/key
|
||||
- "git-crypt unlock /tmp/key"
|
||||
- name: Run renew script
|
||||
image: alpine
|
||||
environment:
|
||||
TF_VAR_prod: "true"
|
||||
commands:
|
||||
- "apk update && apk add git certbot expect curl gzip"
|
||||
# Install terraform cli
|
||||
- "curl https://releases.hashicorp.com/terraform/0.14.6/terraform_0.14.6_linux_amd64.zip | gzip -d > /usr/local/bin/terraform && chmod 775 /usr/local/bin/terraform"
|
||||
- "terraform init"
|
||||
- "./modules/kubernetes/setup_tls_secret/renew.sh"
|
||||
- name: Commit updated certificates
|
||||
image: alpine
|
||||
commands:
|
||||
- "apk update && apk add openssh-client git git-crypt"
|
||||
- "mkdir ~/.ssh && ssh-keyscan -H github.com >> ~/.ssh/known_hosts"
|
||||
- 'chmod 400 secrets/deploy_key'
|
||||
- "git add ."
|
||||
- "git remote set-url origin git@github.com:ViktorBarzin/infra.git"
|
||||
- "git commit -m 'Drone CI Update TLS Certificates Commit' || echo 'No changes'"
|
||||
- "GIT_SSH_COMMAND='ssh -i ./secrets/deploy_key -o IdentitiesOnly=yes' git push origin master"
|
||||
|
|
|
|||
5
modules/kubernetes/bind/extra/viktorbarzin.me
Normal file
5
modules/kubernetes/bind/extra/viktorbarzin.me
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
; additional bind records added via terraform automation
|
||||
; entries are usually programmatically added to this file
|
||||
|
||||
_acme-challenge IN TXT "6TiErEakwCp5Ryy3ICW8XVm_uGCUU9UhNZv4XFFnOkI"
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ resource "kubernetes_config_map" "bind_configmap" {
|
|||
|
||||
data = {
|
||||
"db.viktorbarzin.lan" = var.db_viktorbarzin_lan
|
||||
"db.viktorbarzin.me" = var.db_viktorbarzin_me
|
||||
"db.viktorbarzin.me" = format("%s%s", var.db_viktorbarzin_me, file("${path.module}/extra/viktorbarzin.me"))
|
||||
"named.conf" = var.named_conf
|
||||
"named.conf.local" = var.named_conf_local
|
||||
"named.conf.options" = var.named_conf_options
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
variable namespace {}
|
||||
variable tls_secret_name {}
|
||||
variable tls_crt {}
|
||||
variable tls_key {}
|
||||
variable "namespace" {}
|
||||
variable "tls_secret_name" {}
|
||||
variable "tls_crt" {
|
||||
default = ""
|
||||
}
|
||||
variable "tls_key" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "tls_secret" {
|
||||
metadata {
|
||||
|
|
@ -9,8 +13,9 @@ resource "kubernetes_secret" "tls_secret" {
|
|||
namespace = var.namespace
|
||||
}
|
||||
data = {
|
||||
"tls.crt" = var.tls_crt
|
||||
"tls.key" = var.tls_key
|
||||
# Cannot set default function in variable so use default behaviour here
|
||||
"tls.crt" = var.tls_crt == "" ? file("${path.root}/secrets/fullchain.pem") : var.tls_crt
|
||||
"tls.key" = var.tls_key == "" ? file("${path.root}/secrets/privkey.pem") : var.tls_key
|
||||
}
|
||||
type = "kubernetes.io/tls"
|
||||
}
|
||||
|
|
|
|||
79
modules/kubernetes/setup_tls_secret/renew.sh
Executable file
79
modules/kubernetes/setup_tls_secret/renew.sh
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/expect -f
|
||||
|
||||
set timeout -1
|
||||
set le_dir "/tmp/le/"
|
||||
set config_dir "$le_dir/out/config"
|
||||
set pwd [pwd]
|
||||
|
||||
spawn certbot certonly --manual --preferred-challenge=dns --email me@viktorbarzin.me --server https://acme-v02.api.letsencrypt.org/directory --agree-tos --manual-public-ip-logging-ok -d *.viktorbarzin.me -d viktorbarzin.me --config-dir $config_dir --work-dir $le_dir/workdir --logs-dir $le_dir/logsdir --no-eff-email
|
||||
|
||||
set prompt "$"
|
||||
set dns_file "$pwd/modules/kubernetes/bind/extra/viktorbarzin.me"
|
||||
expect -re "Before continuing, verify" {
|
||||
set challenge [ exec sh -c "echo '$expect_out(buffer)' | tail -n 3 | head -n 1" ]
|
||||
set dns_record "_acme-challenge IN TXT \"$challenge\""
|
||||
puts $dns_record
|
||||
puts $dns_file
|
||||
|
||||
# Check if dns record is not already present
|
||||
try {
|
||||
set results [exec grep -q $dns_record $dns_file]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
if {$status != 0} {
|
||||
exec echo $dns_record | tee -a $dns_file
|
||||
puts "Teed into file"
|
||||
} else {
|
||||
puts "DNS record '$dns_record' already in file"
|
||||
}
|
||||
}
|
||||
|
||||
send -- "\r"
|
||||
# Do the same for the 2nd dns record
|
||||
expect -re "Before continuing, verify" {
|
||||
set challenge [ exec sh -c "echo '$expect_out(buffer)' | tail -n 3 | head -n 1" ]
|
||||
set dns_record "_acme-challenge IN TXT \"$challenge\""
|
||||
puts $dns_record
|
||||
puts $dns_file
|
||||
|
||||
# Check if dns record is not already present
|
||||
try {
|
||||
set results [exec grep -q $dns_record $dns_file]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
if {$status != 0} {
|
||||
exec echo $dns_record | tee -a $dns_file
|
||||
puts "Teed into file"
|
||||
} else {
|
||||
puts "DNS record '$dns_record' already in file"
|
||||
}
|
||||
}
|
||||
|
||||
# Force deployment recreation
|
||||
exec terraform taint module.kubernetes_cluster.module.bind.module.bind-public-deployment.kubernetes_deployment.bind
|
||||
# Apply changes to configmap and redeploy
|
||||
exec >@stdout 2>@stderr terraform apply -auto-approve -target=module.kubernetes_cluster.module.bind
|
||||
|
||||
# Wait for deployment update
|
||||
# TODO: better to use k8s api. What we want is `kubectl rollout status deployment -l app=bind-public` as a curl
|
||||
# exec bash -c 'while [[ $(kubectl get pods -l app=bind-public -o \'jsonpath={..status.conditions[\?(\@.type=="Ready")].status}\') != "True" ]]; do echo "waiting pod..." && sleep 1; done'
|
||||
exec >@stdout echo 'Waiting for redeployment of bind...'
|
||||
exec sleep 10
|
||||
|
||||
send -- "\r"
|
||||
|
||||
# Clean up
|
||||
exec sed -i "s/$dns_record//g" "$dns_file"
|
||||
|
||||
# Success
|
||||
expect ".*Congratulations!"
|
||||
|
||||
# Copy cert and key to secrets dir
|
||||
exec cp --remove-destination $config_dir/live/viktorbarzin.me/fullchain.pem ./secrets
|
||||
exec cp --remove-destination $config_dir/live/viktorbarzin.me/privkey.pem ./secrets
|
||||
|
||||
puts "Done renewing cert. Output certificates stored in ./secrets\n"
|
||||
BIN
secrets/fullchain.pem
Normal file
BIN
secrets/fullchain.pem
Normal file
Binary file not shown.
BIN
secrets/privkey.pem
Normal file
BIN
secrets/privkey.pem
Normal file
Binary file not shown.
Binary file not shown.
BIN
terraform.tfvars
BIN
terraform.tfvars
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue