diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index cb5d052..8a904cc 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -2,17 +2,18 @@ # To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml version: 0.1 cli: - version: 1.22.2 + version: 1.22.9 # Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins) plugins: sources: - id: trunk - ref: v1.6.1 + ref: v1.6.6 uri: https://github.com/trunk-io/plugins # Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes) runtimes: enabled: - - node@18.12.1 + - go@1.21.0 + - node@18.20.5 - python@3.10.8 # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) lint: @@ -21,14 +22,17 @@ lint: paths: - LICENCE.md enabled: - - actionlint@1.7.1 - - checkov@3.2.216 + - hadolint@2.12.1-beta + - shellcheck@0.10.0 + - shfmt@3.6.0 + - actionlint@1.7.7 + - checkov@3.2.357 - git-diff-check - - markdownlint@0.41.0 - - prettier@3.3.3 - - tflint@0.52.0 - - trivy@0.54.0 - - trufflehog@3.80.3 + - markdownlint@0.43.0 + - prettier@3.4.2 + - tflint@0.55.0 + - trivy@0.58.2 + - trufflehog@3.88.2 - yamllint@1.35.1 actions: enabled: diff --git a/bin/expose b/bin/expose new file mode 100755 index 0000000..dbe18cc Binary files /dev/null and b/bin/expose differ diff --git a/cloud/aws/efs_file_system/security-groups.tf b/cloud/aws/efs_file_system/security-groups.tf index 846d5f7..5179ffe 100644 --- a/cloud/aws/efs_file_system/security-groups.tf +++ b/cloud/aws/efs_file_system/security-groups.tf @@ -13,6 +13,7 @@ resource "aws_security_group" "efs" { }) } resource "aws_vpc_security_group_ingress_rule" "nfs" { + description = "Allow NFS traffic from EFS" ip_protocol = "tcp" from_port = 2049 to_port = 2049 @@ -23,6 +24,7 @@ resource "aws_vpc_security_group_ingress_rule" "nfs" { }) } resource "aws_vpc_security_group_egress_rule" "nfs" { + description = "Allow NFS traffic to EFS" ip_protocol = "tcp" from_port = 2049 to_port = 2049 @@ -32,7 +34,11 @@ resource "aws_vpc_security_group_egress_rule" "nfs" { Name = "NFS/EFS Egress" }) } +# checkov:skip=CKV_AWS_24: checkov is mis-detecting this as exposing port 22 to 0.0.0.0 +# checkov:skip=CKV_AWS_25: checkov is mis-detecting this as exposing port 3389 to 0.0.0.0 +# checkov:skip=CKV_AWS_260: checkov is mis-detecting this as exposing port 80 to 0.0.0.0 resource "aws_vpc_security_group_ingress_rule" "ping" { + description = "Allow ping" ip_protocol = "icmp" from_port = 0 to_port = 0 diff --git a/products/bastion/README.md b/products/bastion/README.md index f37202e..8966b3b 100644 --- a/products/bastion/README.md +++ b/products/bastion/README.md @@ -1 +1 @@ -Heavy use of code pilfered from https://github.com/binlab/docker-bastion/blob/master/Dockerfile \ No newline at end of file +Heavy use of code pilfered from https://github.com/binlab/docker-bastion/blob/master/Dockerfile diff --git a/products/bastion/bastion.sh b/products/bastion/bastion.sh index 1129d5b..5a45a08 100644 --- a/products/bastion/bastion.sh +++ b/products/bastion/bastion.sh @@ -1,90 +1,89 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash HOST_KEYS_PATH_PREFIX="${HOST_KEYS_PATH_PREFIX:='/'}" HOST_KEYS_PATH="${HOST_KEYS_PATH:='/etc/ssh'}" -if [ "$PUBKEY_AUTHENTICATION" == "false" ]; then - CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=no" +if [[ ${PUBKEY_AUTHENTICATION} == "false" ]]; then + CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=no" else - CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=yes" + CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=yes" fi -if [ -n "$AUTHORIZED_KEYS" ]; then - CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=$AUTHORIZED_KEYS" +if [[ -n ${AUTHORIZED_KEYS} ]]; then + CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=${AUTHORIZED_KEYS}" else - CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=authorized_keys" + CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=authorized_keys" fi -if [ -n "$TRUSTED_USER_CA_KEYS" ]; then - CONFIG_TRUSTED_USER_CA_KEYS="-o TrustedUserCAKeys=$TRUSTED_USER_CA_KEYS" - CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u" +if [[ -n ${TRUSTED_USER_CA_KEYS} ]]; then + CONFIG_TRUSTED_USER_CA_KEYS="-o TrustedUserCAKeys=${TRUSTED_USER_CA_KEYS}" + CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u" else - CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u" + CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u" fi - -if [ "$GATEWAY_PORTS" == "true" ]; then - CONFIG_GATEWAY_PORTS="-o GatewayPorts=yes" +if [[ ${GATEWAY_PORTS} == "true" ]]; then + CONFIG_GATEWAY_PORTS="-o GatewayPorts=yes" else - CONFIG_GATEWAY_PORTS="-o GatewayPorts=no" + CONFIG_GATEWAY_PORTS="-o GatewayPorts=no" fi -if [ "$PERMIT_TUNNEL" == "true" ]; then - CONFIG_PERMIT_TUNNEL="-o PermitTunnel=yes" +if [[ ${PERMIT_TUNNEL} == "true" ]]; then + CONFIG_PERMIT_TUNNEL="-o PermitTunnel=yes" else - CONFIG_PERMIT_TUNNEL="-o PermitTunnel=no" + CONFIG_PERMIT_TUNNEL="-o PermitTunnel=no" fi -if [ "$X11_FORWARDING" == "true" ]; then - CONFIG_X11_FORWARDING="-o X11Forwarding=yes" +if [[ ${X11_FORWARDING} == "true" ]]; then + CONFIG_X11_FORWARDING="-o X11Forwarding=yes" else - CONFIG_X11_FORWARDING="-o X11Forwarding=no" + CONFIG_X11_FORWARDING="-o X11Forwarding=no" fi -if [ "$TCP_FORWARDING" == "false" ]; then - CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=no" +if [[ ${TCP_FORWARDING} == "false" ]]; then + CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=no" else - CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=yes" + CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=yes" fi -if [ "$AGENT_FORWARDING" == "false" ]; then - CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=no" +if [[ ${AGENT_FORWARDING} == "false" ]]; then + CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=no" else - CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=yes" + CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=yes" fi -if [ ! -f "$HOST_KEYS_PATH/ssh_host_rsa_key" ]; then - /usr/bin/ssh-keygen -A -f "$HOST_KEYS_PATH_PREFIX" +if [[ ! -f "${HOST_KEYS_PATH}/ssh_host_rsa_key" ]]; then + /usr/bin/ssh-keygen -A -f "${HOST_KEYS_PATH_PREFIX}" fi -if [ -n "$LISTEN_ADDRESS" ]; then - CONFIG_LISTEN_ADDRESS="-o ListenAddress=$LISTEN_ADDRESS" +if [[ -n ${LISTEN_ADDRESS} ]]; then + CONFIG_LISTEN_ADDRESS="-o ListenAddress=${LISTEN_ADDRESS}" else - CONFIG_LISTEN_ADDRESS="-o ListenAddress=0.0.0.0" + CONFIG_LISTEN_ADDRESS="-o ListenAddress=0.0.0.0" fi -if [ -n "$LISTEN_PORT" ]; then - CONFIG_LISTEN_PORT="-o Port=$LISTEN_PORT" +if [[ -n ${LISTEN_PORT} ]]; then + CONFIG_LISTEN_PORT="-o Port=${LISTEN_PORT}" else - CONFIG_LISTEN_PORT="-o Port=22" + CONFIG_LISTEN_PORT="-o Port=22" fi /usr/sbin/sshd -D -e -4 \ - -o "HostKey=$HOST_KEYS_PATH/ssh_host_rsa_key" \ - -o "HostKey=$HOST_KEYS_PATH/ssh_host_dsa_key" \ - -o "HostKey=$HOST_KEYS_PATH/ssh_host_ecdsa_key" \ - -o "HostKey=$HOST_KEYS_PATH/ssh_host_ed25519_key" \ - -o "PasswordAuthentication=no" \ - -o "PermitEmptyPasswords=no" \ - -o "PermitRootLogin=no" \ - $CONFIG_PUBKEY_AUTHENTICATION \ - $CONFIG_AUTHORIZED_KEYS \ - $CONFIG_GATEWAY_PORTS \ - $CONFIG_PERMIT_TUNNEL \ - $CONFIG_X11_FORWARDING \ - $CONFIG_AGENT_FORWARDING \ - $CONFIG_TCP_FORWARDING \ - $CONFIG_TRUSTED_USER_CA_KEYS \ - $CONFIG_AUTHORIZED_PRINCIPALS_FILE \ - $CONFIG_LISTEN_ADDRESS \ - $CONFIG_LISTEN_PORT + -o "HostKey=${HOST_KEYS_PATH}/ssh_host_rsa_key" \ + -o "HostKey=${HOST_KEYS_PATH}/ssh_host_dsa_key" \ + -o "HostKey=${HOST_KEYS_PATH}/ssh_host_ecdsa_key" \ + -o "HostKey=${HOST_KEYS_PATH}/ssh_host_ed25519_key" \ + -o "PasswordAuthentication=no" \ + -o "PermitEmptyPasswords=no" \ + -o "PermitRootLogin=no" \ + "${CONFIG_PUBKEY_AUTHENTICATION}" \ + "${CONFIG_AUTHORIZED_KEYS}" \ + "${CONFIG_GATEWAY_PORTS}" \ + "${CONFIG_PERMIT_TUNNEL}" \ + "${CONFIG_X11_FORWARDING}" \ + "${CONFIG_AGENT_FORWARDING}" \ + "${CONFIG_TCP_FORWARDING}" \ + "${CONFIG_TRUSTED_USER_CA_KEYS}" \ + "${CONFIG_AUTHORIZED_PRINCIPALS_FILE}" \ + "${CONFIG_LISTEN_ADDRESS}" \ + "${CONFIG_LISTEN_PORT}" diff --git a/products/bastion/docker-compose.yml b/products/bastion/docker-compose.yml index d0ca336..8028ff0 100644 --- a/products/bastion/docker-compose.yml +++ b/products/bastion/docker-compose.yml @@ -33,4 +33,4 @@ services: target: /var/lib/bastion/authorized_keys volumes: - bastion: \ No newline at end of file + bastion: diff --git a/products/expose/auth.tf b/products/expose/auth.tf new file mode 100644 index 0000000..8a80f71 --- /dev/null +++ b/products/expose/auth.tf @@ -0,0 +1,24 @@ +variable "username" { + type = string + description = "The username to use for the service." + default = null +} +variable "password" { + type = string + description = "The password to use for the service." + default = null +} +resource "random_pet" "username" { + count = var.username == null ? 1 : 0 + length = 2 + separator = "" +} +resource "random_string" "password" { + count = var.username == null ? 1 : 0 + length = 32 + special = false +} +locals { + username = var.username != null ? var.username : random_pet.username[0].id + password = var.password != null ? var.password : nonsensitive(random_string.password[0].result) +} \ No newline at end of file diff --git a/products/expose/expose.tf b/products/expose/expose.tf new file mode 100644 index 0000000..a45b64c --- /dev/null +++ b/products/expose/expose.tf @@ -0,0 +1,26 @@ +variable "domain" { + type = string + description = "The domain to use for the service." +} +module "service" { + source = "../../docker/service" + image = "beyondcodegmbh/expose-server:latest" + service_name = "expose" + stack_name = var.stack_name + networks = concat(var.networks, [module.network.network]) + traefik = var.traefik + placement_constraints = var.placement_constraints + mounts = var.mounts + ports = var.ports + converge_enable = false + environment_variables = { + port = 9090 + domain = var.domain + username = local.username + password = local.password + } + volumes = { + "expose_data" = "/root/.expose" + } +} + diff --git a/products/expose/inputs.tf b/products/expose/inputs.tf new file mode 100644 index 0000000..bc1e85b --- /dev/null +++ b/products/expose/inputs.tf @@ -0,0 +1,45 @@ +variable "stack_name" { + default = "expose" + type = string + description = "The name of the stack to create." +} +variable "networks" { + type = list(object({ + name = string + id = string + })) + default = [] + description = "A list of network names to attach the service to." +} +variable "traefik" { + default = null + type = object({ + domain = string + port = optional(number) + non-ssl = optional(bool, true) + ssl = optional(bool, false) + rule = optional(string) + middlewares = optional(list(string)) + network = optional(object({ name = string, id = string })) + basic-auth-users = optional(list(string)) + }) + description = "Whether to enable traefik for the service." +} +variable "placement_constraints" { + default = [] + type = list(string) + description = "Docker Swarm placement constraints" +} +variable "mounts" { + type = map(string) + default = {} + description = "A map of host paths to container paths to mount. The key is the host path, and the value is the container path." +} +variable "ports" { + type = list(object({ + host = optional(number, null) + container = number + protocol = optional(string, "tcp") + })) + default = [] +} \ No newline at end of file diff --git a/products/expose/network.tf b/products/expose/network.tf new file mode 100644 index 0000000..2306555 --- /dev/null +++ b/products/expose/network.tf @@ -0,0 +1,4 @@ +module "network" { + source = "../../docker/network" + stack_name = var.stack_name +} \ No newline at end of file diff --git a/products/expose/outputs.tf b/products/expose/outputs.tf new file mode 100644 index 0000000..db6f510 --- /dev/null +++ b/products/expose/outputs.tf @@ -0,0 +1,15 @@ +output "docker_service" { + value = module.service.docker_service +} +output "network" { + value = module.network.network +} +output "endpoint" { + value = module.service.endpoint +} +output "auth" { + value = { + username = local.username + password = local.password + } +} \ No newline at end of file diff --git a/products/expose/terraform.tf b/products/expose/terraform.tf new file mode 100644 index 0000000..ff5e3bd --- /dev/null +++ b/products/expose/terraform.tf @@ -0,0 +1,16 @@ +terraform { + required_version = "~> 1.6" + + required_providers { + docker = { + source = "kreuzwerker/docker" + version = "~> 3.0" + } + random = { + source = "hashicorp/random" + version = "~> 3.5" + } + } +} + + diff --git a/products/memcached/memcached.tf b/products/memcached/memcached.tf index aee7352..38b5b1a 100644 --- a/products/memcached/memcached.tf +++ b/products/memcached/memcached.tf @@ -4,7 +4,7 @@ module "service" { stack_name = var.stack_name service_name = var.service_name networks = var.networks - command = ["memcached", "--memory-limit", var.memory_limit_mb, "--threads", var.threads, "--connection-limit", var.connection_limit] + command = ["memcached", "-m", var.memory_limit_mb, "-t", var.threads, "-c", var.connection_limit] #healthcheck = ["CMD-SHELL", "echo \"version\" | nc -vn -w 1 127.0.0.1 11211"] #healthcheck_start_period = "10s" #healthcheck_interval = "10s" @@ -21,8 +21,5 @@ locals { volumes = var.data_persist_path == null ? { "data" = "/var/lib/mysql" } : {} - mounts = var.data_persist_path != null ? { - "${var.data_persist_path}" = "/var/lib/mysql" - } : {} - + mounts = var.data_persist_path != null ? zipmap([var.data_persist_path], ["/var/lib/mysql"]) : {} } \ No newline at end of file diff --git a/products/mysql/mysql.tf b/products/mysql/mysql.tf index 489f14d..51d1c4b 100644 --- a/products/mysql/mysql.tf +++ b/products/mysql/mysql.tf @@ -24,8 +24,5 @@ locals { volumes = var.data_persist_path == null ? { "data" = "/var/lib/mysql" } : {} - mounts = var.data_persist_path != null ? { - "${var.data_persist_path}" = "/var/lib/mysql" - } : {} - + mounts = var.data_persist_path != null ? zipmap([var.data_persist_path], ["/var/lib/mysql"]) : {} } \ No newline at end of file diff --git a/products/openhaystack/inputs.tf b/products/openhaystack/inputs.tf index 50bc777..4691669 100644 --- a/products/openhaystack/inputs.tf +++ b/products/openhaystack/inputs.tf @@ -9,7 +9,7 @@ variable "networks" { })) default = [] description = "A list of network names to attach the service to." -} +}/* variable "ports" { type = list(object({ host = optional(number) @@ -30,7 +30,7 @@ variable "ports" { error_message = "Protocol must be either 'tcp' or 'udp'." condition = alltrue([for port in var.ports : port.protocol == "tcp" || port.protocol == "udp"]) } -} +}*/ variable "placement_constraints" { default = [] type = list(string) diff --git a/products/openhaystack/openhaystack.tf b/products/openhaystack/openhaystack.tf index 90b636c..68fec1e 100644 --- a/products/openhaystack/openhaystack.tf +++ b/products/openhaystack/openhaystack.tf @@ -15,7 +15,6 @@ module "anisette" { "anisette-v3-data" = "/home/Alcoholic/.config/anisette-v3/lib/" } } - module "macless-haystack" { source = "../../docker/service" stack_name = var.stack_name diff --git a/products/postgres/inputs.tf b/products/postgres/inputs.tf index 0030a3d..d490bee 100644 --- a/products/postgres/inputs.tf +++ b/products/postgres/inputs.tf @@ -1,3 +1,8 @@ +variable "enable" { + type = bool + description = "Whether to enable the service." + default = true +} variable "postgres_image" { default = "postgres" type = string diff --git a/products/postgres/postgres.tf b/products/postgres/postgres.tf index d6a9931..4af45fa 100644 --- a/products/postgres/postgres.tf +++ b/products/postgres/postgres.tf @@ -1,5 +1,6 @@ module "service" { source = "../../docker/service" + enable = var.enable image = "${var.postgres_image}:${var.postgres_version}" stack_name = var.stack_name service_name = var.service_name @@ -16,13 +17,9 @@ module "service" { ports = var.ports placement_constraints = var.placement_constraints } - locals { volumes = var.data_persist_path == null ? { "data" = "/var/lib/postgres/data" } : {} - mounts = var.data_persist_path != null ? { - "${var.data_persist_path}" = "/var/lib/postgres/data" - } : {} - + mounts = var.data_persist_path != null ? zipmap([var.data_persist_path], ["/var/lib/postgres/data"]) : {} } \ No newline at end of file diff --git a/products/quassel/inputs.tf b/products/quassel/inputs.tf index 37fabad..2e17039 100644 --- a/products/quassel/inputs.tf +++ b/products/quassel/inputs.tf @@ -1,3 +1,8 @@ +variable "enable" { + type = bool + description = "Whether to enable the service." + default = true +} variable "quassel_image" { default = "lscr.io/linuxserver/quassel-core" type = string diff --git a/products/quassel/quassel.tf b/products/quassel/quassel.tf index 8751b47..deda3a9 100644 --- a/products/quassel/quassel.tf +++ b/products/quassel/quassel.tf @@ -4,16 +4,17 @@ module "network" { } module "postgres" { source = "../postgres" + enable = var.enable postgres_version = "16" stack_name = var.stack_name networks = [module.network] username = "postgres" database = "postgres" placement_constraints = var.placement_constraints - ports = [{ container = 5432, host = 65432 }] } module "service" { source = "../../docker/service" + enable = var.enable image = "${var.quassel_image}:${var.quassel_version}" stack_name = var.stack_name service_name = "quassel" diff --git a/products/redis/inputs.tf b/products/redis/inputs.tf index 246622e..07c000a 100644 --- a/products/redis/inputs.tf +++ b/products/redis/inputs.tf @@ -1,3 +1,8 @@ +variable "enable" { + type = bool + description = "Whether to enable the service." + default = true +} variable "redis_image" { default = "redis" type = string diff --git a/products/redis/redis.tf b/products/redis/redis.tf index bdbf802..c386350 100644 --- a/products/redis/redis.tf +++ b/products/redis/redis.tf @@ -24,6 +24,7 @@ variable "append_only" { } module "service" { source = "../../docker/service" + enable = var.enable image = "${var.redis_image}:${var.redis_version}" stack_name = var.stack_name service_name = "redis" diff --git a/products/unifi/magic-forward/magic_forward.tf b/products/unifi/magic-forward/magic_forward.tf index df6134b..3ba4b3a 100644 --- a/products/unifi/magic-forward/magic_forward.tf +++ b/products/unifi/magic-forward/magic_forward.tf @@ -4,4 +4,5 @@ module "port_forward" { label = var.label port = var.port != null ? var.port : var.docker_service.endpoint_spec[0].ports[0].published_port ip = var.target.fixed_ip + protocol = var.protocol } \ No newline at end of file diff --git a/products/watchtower/watchtower.tf b/products/watchtower/watchtower.tf index 31ca443..06946c0 100644 --- a/products/watchtower/watchtower.tf +++ b/products/watchtower/watchtower.tf @@ -3,7 +3,7 @@ module "watchtower" { image = "containrrr/watchtower:latest" stack_name = "watchtower" service_name = "watchtower" - placement_constraints = var.placement_constraints + ["node.role == manager"] + placement_constraints = distinct(concat(var.placement_constraints, ["node.role == manager"])) command = ["--cleanup", "--label-enable", "--interval", "3600"] labels = { "com.centurylinklabs.watchtower.enable" = "true" diff --git a/products/yarr/inputs.tf b/products/yarr/inputs.tf index 5e04192..2864997 100644 --- a/products/yarr/inputs.tf +++ b/products/yarr/inputs.tf @@ -1,3 +1,8 @@ +variable "enabled" { + description = "Whether to enable the services or merely provision them." + type = bool + default = true +} variable "stack_name" { description = "The name of the stack" type = string @@ -16,7 +21,6 @@ variable "placement_constraints" { default = [] } variable "traefik" { - default = null type = object({ domain = string port = optional(number) @@ -29,8 +33,3 @@ variable "traefik" { }) description = "Whether to enable traefik for the service." } -variable "enabled" { - description = "Whether to enable the services or merely provision them." - type = bool - default = true -} \ No newline at end of file diff --git a/utils/identity/locals.tf b/utils/identity/locals.tf index 141a809..83f9082 100644 --- a/utils/identity/locals.tf +++ b/utils/identity/locals.tf @@ -1,5 +1,4 @@ locals { - username_words = var.username_words != null ? var.username_words : floor(var.username_max_length / 3) username = var.username != null ? var.username : random_pet.username[0].id password = var.password != null ? nonsensitive(var.password) : nonsensitive(random_password.password[0].result) } \ No newline at end of file