added providers, fleshed out terraform

This commit is contained in:
Mike Kell 2025-04-22 22:46:07 +00:00
parent 9b028b095e
commit 8f3291499f
30 changed files with 358 additions and 25 deletions

View File

@ -0,0 +1,10 @@
- name: Log evidence
include_role:
name: evidence_logger
vars:
log_file: "dns_check.log"
log_content: |
mail.example.com -> 203.0.113.10
auth.example.com -> 203.0.113.11
summary_entry: "✅ DNS resolution for example.com"
validation_entry: "DNS check completed and passed for fqdn_root: example.com"

View File

@ -1,8 +1,14 @@
#!/bin/bash #!/bin/bash
apt update && apt install -y git python3-pip curl ufw set -e
pip3 install ansible
ufw allow OpenSSH echo "🔧 Initializing Terraform..."
ufw --force enable terraform init
git clone https://github.com/mtkell/open-cmmc-stack.git /opt/open-cmmc-stack
cd /opt/open-cmmc-stack/ansible echo "📐 Running Terraform plan..."
ansible-playbook -i localhost, secure_ubuntu.yml terraform plan -var-file=terraform.tfvars
echo "🚀 Applying Terraform configuration..."
terraform apply -auto-approve -var-file=terraform.tfvars
echo "✅ Done. Review outputs below:"
terraform output

View File

View File

View File

0
terraform/dns/gcp_dns.tf Normal file
View File

0
terraform/dns/godaddy.tf Normal file
View File

0
terraform/dns/route53.tf Normal file
View File

View File

View File

@ -1,18 +1,36 @@
provider "digitalocean" { terraform {
token = var.do_token required_version = ">= 1.3.0"
required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.0"
}
}
} }
resource "digitalocean_droplet" "secure_host" { provider "local" {}
name = "cmmc-hardened"
region = "nyc3"
size = "s-2vcpu-4gb"
image = "ubuntu-22-04-x64"
ssh_keys = [var.ssh_fingerprint]
user_data = file("${path.module}/bootstrap.sh")
tags = ["cmmc", "secure-host"] locals {
services = var.vm_definitions
} }
output "droplet_ip" { module "vm" {
value = digitalocean_droplet.secure_host.ipv4_address source = "./modules/vm"
for_each = local.services
service_name = each.key
provider = var.infrastructure_provider
region = each.value.region
tags = each.value.tags
}
# Create a DNS A record for each deployed service
module "dns" {
source = "./modules/dns_record"
for_each = local.services
zone_id = var.cloudflare_zone_id
subdomain = each.key
ip_address = module.vm[each.key].ip_address
} }

View File

@ -0,0 +1,8 @@
resource "cloudflare_record" "dns" {
zone_id = var.zone_id
name = var.subdomain
type = "A"
value = var.ip_address
ttl = 300
proxied = false
}

View File

@ -0,0 +1,3 @@
output "fqdn" {
value = "${var.subdomain}.${var.root_domain}"
}

View File

@ -0,0 +1,14 @@
variable "zone_id" {
description = "Cloudflare Zone ID"
type = string
}
variable "subdomain" {
description = "Subdomain to create (e.g., mail, auth)"
type = string
}
variable "ip_address" {
description = "Public IP address to point the A record to"
type = string
}

View File

@ -0,0 +1,10 @@
resource "aws_instance" "vm" {
count = var.provider == "aws" ? 1 : 0
ami = var.aws_ami
instance_type = "t3.micro"
key_name = var.ssh_key_name
tags = merge(
var.tags,
{ Name = "open-cmmc-${var.service_name}" }
)
}

View File

@ -0,0 +1,15 @@
resource "azurerm_linux_virtual_machine" "vm" {
count = var.provider == "azure" ? 1 : 0
name = "open-cmmc-${var.service_name}"
resource_group_name = var.azure_resource_group
location = var.region
size = "Standard_B1s"
admin_username = "ubuntu"
admin_ssh_key {
username = "ubuntu"
public_key = var.ssh_public_key
}
network_interface_ids = [var.azure_nic_id]
}

View File

@ -0,0 +1,9 @@
resource "digitalocean_droplet" "vm" {
count = var.provider == "digitalocean" ? 1 : 0
name = "open-cmmc-${var.service_name}"
region = var.region
image = "ubuntu-22-04-x64"
size = "s-1vcpu-1gb"
ssh_keys = var.ssh_keys
tags = [for tag_key, tag_value in var.tags : "${tag_key}:${tag_value}"]
}

View File

@ -0,0 +1,23 @@
resource "google_compute_instance" "vm" {
count = var.provider == "gcp" ? 1 : 0
name = "open-cmmc-${var.service_name}"
machine_type = "e2-medium"
zone = var.gcp_zone
boot_disk {
initialize_params {
image = "ubuntu-os-cloud/ubuntu-2204-lts"
}
}
network_interface {
network = "default"
access_config {} # This allocates a one-to-one NAT IP
}
metadata = {
ssh-keys = "ubuntu:${var.ssh_public_key}"
}
tags = [for tag_key, tag_value in var.tags : "${tag_key}:${tag_value}"]
}

View File

@ -0,0 +1,14 @@
resource "digitalocean_droplet" "vm" {
name = "open-cmmc-${var.service_name}"
region = var.region
size = "s-1vcpu-1gb"
image = "ubuntu-22-04-x64"
tags = [for tag_key, tag_value in var.tags : "${tag_key}:${tag_value}"]
ssh_keys = var.ssh_keys
lifecycle {
ignore_changes = [image]
}
}

View File

@ -0,0 +1,10 @@
output "ip_address" {
value = (
var.provider == "digitalocean" && length(digitalocean_droplet.vm) > 0 ? digitalocean_droplet.vm[0].ipv4_address :
var.provider == "aws" && length(aws_instance.vm) > 0 ? aws_instance.vm[0].public_ip :
var.provider == "azure" && length(azurerm_linux_virtual_machine.vm) > 0 ? azurerm_linux_virtual_machine.vm[0].public_ip_address :
var.provider == "gcp" && length(google_compute_instance.vm) > 0 ? google_compute_instance.vm[0].network_interface[0].access_config[0].nat_ip :
var.provider == "proxmox" ? proxmox_vm_qemu.vm[0].ipconfig0 :
null
)
}

View File

@ -0,0 +1,7 @@
resource "proxmox_vm_qemu" "vm" {
count = var.provider == "proxmox" ? 1 : 0
name = "open-cmmc-${var.service_name}"
target_node = var.proxmox_node
clone = var.proxmox_template
...
}

View File

@ -0,0 +1,50 @@
variable "ssh_keys" {
description = "List of DigitalOcean SSH key fingerprints or IDs"
type = list(string)
}
variable "aws_ami" {
description = "AMI ID to use for AWS EC2 instance"
type = string
default = "ami-0c55b159cbfafe1f0" # Ubuntu 22.04 in us-east-1 (example)
}
variable "ssh_key_name" {
description = "AWS SSH key pair name"
type = string
}
variable "azure_resource_group" {
description = "Azure resource group name"
type = string
}
variable "azure_nic_id" {
description = "Azure network interface ID"
type = string
}
variable "ssh_public_key" {
description = "Public SSH key for Azure admin login"
type = string
}
variable "gcp_project_id" {
description = "Google Cloud Project ID"
type = string
}
variable "gcp_region" {
description = "Google Cloud region"
type = string
}
variable "gcp_zone" {
description = "Google Cloud zone"
type = string
}
variable "gcp_credentials_file" {
description = "Path to GCP service account JSON key file"
type = string
}

24
terraform/outputs,tf Normal file
View File

@ -0,0 +1,24 @@
# Output all service names
output "vm_services" {
value = keys(module.vm)
description = "List of deployed service names"
}
# Output tags per service
output "vm_tags" {
value = {
for service, mod in module.vm : service => mod.vm_service_tag
}
description = "Tags assigned per service VM"
}
# Placeholder for service-level info until actual providers are implemented
output "vm_placeholders" {
value = {
for service, mod in module.vm : service => {
service_tag = mod.vm_service_tag
ip_address = "PLACEHOLDER"
}
}
description = "Service-level IPs and tags (will be replaced with real outputs later)"
}

View File

View File

View File

View File

@ -0,0 +1,5 @@
provider "digitalocean" {
token = var.digitalocean_token
}
# Optionally configure default region or other settings here

View File

@ -0,0 +1,6 @@
provider "google" {
project = var.gcp_project_id
region = var.gcp_region
zone = var.gcp_zone
credentials = file(var.gcp_credentials_file)
}

View File

@ -0,0 +1,6 @@
provider "proxmox" {
pm_api_url = var.proxmox_api_url
pm_user = var.proxmox_user
pm_password = var.proxmox_password
pm_tls_insecure = true
}

View File

@ -1,2 +1,62 @@
do_token = "your_digitalocean_token_here" # Base domain for TLS and reverse proxy
ssh_fingerprint = "your_local_ssh_key_fingerprint" fqdn_root = "example.com"
# Choose your provider: aws, azure, gcp, digitalocean, proxmox
infrastructure_provider = "digitalocean"
# Define which services should be deployed, and where
vm_definitions = {
mail = {
region = "nyc3"
tags = {
role = "mail"
purpose = "email"
}
}
files = {
region = "nyc3"
tags = {
role = "file_storage"
purpose = "nextcloud"
}
}
auth = {
region = "nyc3"
tags = {
role = "identity"
purpose = "keycloak"
}
}
}
# infrastructure_provider = "aws"
# aws_ami = "ami-0c55b159cbfafe1f0"
# ssh_key_name = "my-aws-keypair"
# infrastructure_provider = "azure"
# azure_resource_group = "my-cmmc-resources"
# azure_nic_id = "/subscriptions/.../resourceGroups/.../providers/Microsoft.Network/networkInterfaces/..."
# ssh_public_key = "ssh-rsa AAAAB3Nza...your-key-here"
# infrastructure_provider = "gcp"
# gcp_project_id = "your-gcp-project-id"
# gcp_region = "us-central1"
# gcp_zone = "us-central1-a"
# gcp_credentials_file = "gcp-service-account.json"
# ssh_public_key = "ssh-rsa AAAAB3Nza...your-key-here"
# ⚙️ Proxmox Example (uncomment to use)
# infrastructure_provider = "proxmox"
# proxmox_api_url = "https://192.168.1.100:8006/api2/json"
# proxmox_user = "root@pam"
# proxmox_password = "yourpassword"
# proxmox_node = "pve"
# proxmox_template = "ubuntu-22.04-template"
# ssh_public_key = "ssh-rsa AAAAB3Nza...your-key-here"
# dns_provider = "cloudflare"
# fqdn_root = "example.com"
# cloudflare_api_token = "your-cloudflare-api-token"
# cloudflare_zone_id = "your-cloudflare-zone-id"

View File

@ -1,10 +1,45 @@
variable "do_token" { variable "fqdn_root" {
description = "DigitalOcean API token" description = "Base domain used for subdomain routing (e.g., example.com)"
type = string
}
variable "infrastructure_provider" {
description = "Target infrastructure provider (e.g., aws, azure, gcp, digitalocean, proxmox)"
type = string
}
variable "vm_definitions" {
description = "Map of service names to regions and tags"
type = map(object({
region = string
tags = map(string)
}))
}
variable "digitalocean_token" {
description = "API token for DigitalOcean"
type = string type = string
sensitive = true sensitive = true
} }
variable "ssh_fingerprint" { variable "proxmox_api_url" { ... }
description = "Your public SSH key fingerprint registered with DigitalOcean" variable "proxmox_user" { ... }
variable "proxmox_password" { ... }
variable "proxmox_node" { ... }
variable "proxmox_template" { ... }
variable "fqdn_root" {
description = "Base domain for DNS records (e.g., example.com)"
type = string
}
variable "cloudflare_api_token" {
description = "API token for Cloudflare with DNS edit permissions"
type = string
sensitive = true
}
variable "cloudflare_zone_id" {
description = "Zone ID of the domain in Cloudflare"
type = string type = string
} }