Skip to content

Instantly share code, notes, and snippets.

@joscha
Last active November 17, 2025 13:14
Show Gist options
  • Select an option

  • Save joscha/f6c8a0dc8ef9692def997b5699f7875a to your computer and use it in GitHub Desktop.

Select an option

Save joscha/f6c8a0dc8ef9692def997b5699f7875a to your computer and use it in GitHub Desktop.
Spanning backup terraform setup for private key usage
data "aws_caller_identity" "current" {}
resource "aws_kms_key" "spanning" {
bypass_policy_lockout_safety_check = false
description = <<-EOT
Encryption key for Spanning.
DO NOT DELETE THIS KEY, or you will lose access to your data.
EOT
region = var.spanning_region
policy = jsonencode({
Id = "key-consolepolicy-3"
Statement = [
{
Action = "kms:*"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
}
Resource = "*"
Sid = "Enable IAM User Permissions"
},
{
Sid = "Allow access for Key Administrators"
Effect = "Allow"
Principal = {
# TODO: import the user from the account
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/my-aws-user"
}
Action = [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
# Do not allow deletion of the key
# "kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:RotateKeyOnDemand",
]
Resource = "*"
},
{
Sid = "Allow use of the key"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${var.spanning_iam_role_id}:root"
}
Action = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
]
Resource = "*"
},
{
Sid = "Allow attachment of persistent resources"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${var.spanning_iam_role_id}:root"
}
Action = [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant",
]
Condition = {
Bool = {
"kms:GrantIsForAWSResource" = "true"
}
}
Resource = "*"
}
],
Version = "2012-10-17"
})
}
resource "aws_kms_alias" "spanning" {
name = "alias/Spanning-KMS"
target_key_id = aws_kms_key.spanning.key_id
}
resource "aws_organizations_policy" "delete_spanning_key" {
name = "prevent-delete-spanning-key"
description = "Prevent the deletion of the Spanning backup key"
content = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Deny"
Action = [
"kms:ScheduleKeyDeletion",
"kms:Delete*"
]
Resource = aws_kms_key.spanning.arn
}
]
})
}
output "spanning_key_arn" {
value = aws_kms_key.spanning.arn
}
provider "aws" {
region = var.spanning_region
}
# AWS account ID
account_id = "YOUR_ID"
spanning_region = "eu-west-1"
# Spanning's IAM role ID
# See https://www.spanning.com/media/downloads/SBO365-customer-managed-encryption-keys.pdf
spanning_iam_role_id = 877583873091
# tflint-ignore: terraform_unused_declarations
variable "account_id" {
description = "The AWS account ID"
type = string
}
variable "spanning_region" {
description = "The region where the Spanning backup is located"
type = string
}
variable "spanning_iam_role_id" {
description = "The ID of the IAM role to use for Spanning"
type = number
}
terraform {
required_version = ">= 1.8.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0.0"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment