secrets: tf provider sops -> tfvars
This commit is contained in:
parent
39103a0015
commit
57beb5595f
|
@ -0,0 +1,22 @@
|
||||||
|
tf_cloud_token: ENC[AES256_GCM,data:XkG5QZ6Ul4tIZELgDE3gBwa+iwyUY175L+szDpfz2u/n345LjDwWAqcbwsSm/c6YRUlxdH1WDvNKUWwnlSyD56ksrfO5t0vqPbIQIeHAD/XlCM21lkiPp1hc,iv:2gTTM5jgDZ39LNjlGgv18RVSAEzBOT0soQ6ip5RFbk4=,tag:JPPyvWxXnV0s9Avp5y9iNA==,type:str]
|
||||||
|
hcloud_api_token: ENC[AES256_GCM,data:sJW3nPzVKAn2tLJGKcGi7iuA6WfB3B/06R0E5gsOMDLBYMznRnHyP0BtRyLRxfk4RpMAgWI8QWxn7VQsAXjNzw==,iv:RL5JTCy+oU7B9feRZFnKHCFmaEW7O7PB5xzFUpjDhM8=,tag:3S9rJPj5C0DhgCmn2Um/uA==,type:str]
|
||||||
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
|
age:
|
||||||
|
- recipient: age1d53yeje0ggysc93uptlpufyhpchyyfs006368j8mw9r20uyeeydse3n7aw
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4RTU4Z3hja24wM1JCU2sz
|
||||||
|
UFdRQ2loZ25RdmNQN3ZZZXZOTTFoUk1VVVg4ClBybkJoeW5kTDY1TndsYUFQREVr
|
||||||
|
TENza0M1TDRLTUtMcTJPS3c4K0R5UnMKLS0tIGRHYzBOQ1JHYnhQN1RDWXFMMVQ3
|
||||||
|
RzNnVTJKSDd0aE41YjRvSmJFVHZDQzQKIvfq+ccMlZ1ypgxrBMOm+On0Nl3GVhKW
|
||||||
|
Y8b//WmiuhmYZueq7ZMp0gT40144cE1HneDyuVRZ1az5XnFv5OGXag==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2024-01-18T17:54:28Z"
|
||||||
|
mac: ENC[AES256_GCM,data:nEwl132d1V7+gzQGP/qTl0/VpX7psgdNzmfLLOhefJZGqoC5INCgt5DVGE4fiHv1yM8Q+3irDuQPvx4N0dt1y7lY+UdhqbAhANtI+OPdbuC5xpLplgTUiaLuiPGLbeDpNZxpgxqXK1oVCJF356rEmLevYmytKO8HUFMt+qZjjqE=,iv:40JxgMB/+CxNvOTSwLpZCijni24stfF+Qg8sps3xTCE=,tag:S/7fsmwfJvuW+hexuA4p2g==,type:str]
|
||||||
|
pgp: []
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.8.1
|
|
@ -1,8 +1,5 @@
|
||||||
*.bck
|
*.bck
|
||||||
|
|
||||||
# sops
|
|
||||||
/secrets.yaml
|
|
||||||
|
|
||||||
# age
|
# age
|
||||||
/keys.txt
|
/keys.txt
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ keys:
|
||||||
|
|
||||||
# actual sops config
|
# actual sops config
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: secrets(\.enc)?\.yaml$
|
- path_regex: \.auto\.tfvars(\.enc)?\.(yaml|json)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *automation
|
- *automation
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# sops
|
|
||||||
/secrets.yaml
|
|
||||||
|
|
||||||
# age
|
# age
|
||||||
/keys.txt
|
/keys.txt
|
||||||
|
|
||||||
|
|
22
README.md
22
README.md
|
@ -17,6 +17,8 @@ Contains [OpenTofu](https://opentofu.org/) code used to manage our infrastructur
|
||||||
nix develop -c $SHELL
|
nix develop -c $SHELL
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Handle [credentials](#secrets)
|
||||||
|
|
||||||
- Applying changes:
|
- Applying changes:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
@ -69,25 +71,26 @@ Contains [OpenTofu](https://opentofu.org/) code used to manage our infrastructur
|
||||||
```
|
```
|
||||||
|
|
||||||
- list it in [`sops`](https://getsops.io/) config file `.sops.yaml`
|
- list it in [`sops`](https://getsops.io/) config file `.sops.yaml`
|
||||||
- key setup: set environment variable `SOPS_AGE_KEY_FILE` or `SOPS_AGE_KEY` so `sops` can locate the secret key to an `age` key pair that has its public key listed in `.sops.yaml`
|
- key setup: set environment variable `SOPS_AGE_KEY_FILE` or `SOPS_AGE_KEY` so `sops` can locate the secret key to an `age` key pair that has its public key listed in `.sops.yaml`, e.g.:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export SOPS_AGE_KEY_FILE=./keys.txt
|
||||||
|
```
|
||||||
|
|
||||||
- encoding secrets:
|
- encoding secrets:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sops -e secrets.yaml > secrets.enc.yaml
|
nix run .#encode
|
||||||
```
|
```
|
||||||
|
|
||||||
- decoding secrets:
|
- decoding secrets:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sops -d secrets.enc.yaml > secrets.yaml
|
nix run .#decode
|
||||||
```
|
```
|
||||||
|
|
||||||
- setting Terraform Cloud credentials, either by:
|
- setting Terraform Cloud credentials, either by:
|
||||||
- reusing the shared session:
|
- decode (as per above) to reuse the shared session
|
||||||
|
|
||||||
```sh
|
|
||||||
source login.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
- log in to the Terraform Cloud backend:
|
- log in to the Terraform Cloud backend:
|
||||||
|
|
||||||
|
@ -97,11 +100,10 @@ Contains [OpenTofu](https://opentofu.org/) code used to manage our infrastructur
|
||||||
|
|
||||||
### Configuring
|
### Configuring
|
||||||
|
|
||||||
Create a file `.auto.tfvars` containing override for any OpenTofu variables, e.g.:
|
In `.auto.tfvars.json` override any OpenTofu variables, e.g.:
|
||||||
|
|
||||||
```tfvars
|
```tfvars
|
||||||
hcloud_location = "nbg1"
|
hcloud_location = "nbg1"
|
||||||
```
|
```
|
||||||
|
|
||||||
## [HCL to Nix](https://gist.github.com/KiaraGrouwstra/249ede6a7dfc00ea44d85bc6bdbcd875)
|
## [HCL to Nix](https://gist.github.com/KiaraGrouwstra/249ede6a7dfc00ea44d85bc6bdbcd875)
|
||||||
|
|
||||||
|
|
29
config.nix
29
config.nix
|
@ -20,13 +20,10 @@ let
|
||||||
# { a = 1; } -> { name = "a"; a = 1; }
|
# { a = 1; } -> { name = "a"; a = 1; }
|
||||||
setNames = lib.mapAttrs (k: v: { name = k; } // v);
|
setNames = lib.mapAttrs (k: v: { name = k; } // v);
|
||||||
|
|
||||||
# "foo" -> "\${data.sops_file.secrets.data[\"foo\"]}"
|
|
||||||
secret = str: lib.tfRef "data.sops_file.secrets.data[\"${str}\"]";
|
|
||||||
|
|
||||||
hetzner = let
|
hetzner = let
|
||||||
|
|
||||||
# https://docs.hetzner.com/cloud/api/getting-started/generating-api-token
|
# https://docs.hetzner.com/cloud/api/getting-started/generating-api-token
|
||||||
token = secret "hcloud_api_token";
|
token = lib.tfRef "var.hcloud_api_token";
|
||||||
|
|
||||||
in { inherit token; };
|
in { inherit token; };
|
||||||
|
|
||||||
|
@ -34,12 +31,6 @@ in rec {
|
||||||
|
|
||||||
terraform = {
|
terraform = {
|
||||||
|
|
||||||
required_providers = {
|
|
||||||
|
|
||||||
sops.source = "carlpett/sops";
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
cloud = {
|
cloud = {
|
||||||
hostname = "app.terraform.io";
|
hostname = "app.terraform.io";
|
||||||
organization = "bij1";
|
organization = "bij1";
|
||||||
|
@ -52,8 +43,6 @@ in rec {
|
||||||
|
|
||||||
provider = {
|
provider = {
|
||||||
|
|
||||||
sops = {};
|
|
||||||
|
|
||||||
# Configure the Hetzner Cloud Provider
|
# Configure the Hetzner Cloud Provider
|
||||||
hcloud.token = lib.mkForce hetzner.token;
|
hcloud.token = lib.mkForce hetzner.token;
|
||||||
|
|
||||||
|
@ -69,6 +58,18 @@ in rec {
|
||||||
# or using -var="hcloud_api_token=..." CLI option
|
# or using -var="hcloud_api_token=..." CLI option
|
||||||
variable = {
|
variable = {
|
||||||
|
|
||||||
|
# suppress warning, otherwise unused here
|
||||||
|
tf_cloud_token = {
|
||||||
|
type = "string";
|
||||||
|
sensitive = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
hcloud_api_token = {
|
||||||
|
type = "string";
|
||||||
|
description = "[Hetzner Cloud API Token](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token)";
|
||||||
|
sensitive = true;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# https://github.com/terranix/terranix-hcloud/blob/main/options.md
|
# https://github.com/terranix/terranix-hcloud/blob/main/options.md
|
||||||
|
@ -82,10 +83,6 @@ in rec {
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
|
|
||||||
sops_file.secrets = {
|
|
||||||
source_file = "secrets.enc.yaml";
|
|
||||||
};
|
|
||||||
|
|
||||||
hcloud_ssh_keys."all_keys" = {};
|
hcloud_ssh_keys."all_keys" = {};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
12
flake.nix
12
flake.nix
|
@ -27,6 +27,7 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
tf = "${pkgs.opentofu}/bin/tofu";
|
tf = "${pkgs.opentofu}/bin/tofu";
|
||||||
|
sops = "${pkgs.sops}/bin/sops";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
defaultPackage = tfConfig;
|
defaultPackage = tfConfig;
|
||||||
|
@ -47,10 +48,8 @@
|
||||||
sops
|
sops
|
||||||
rage
|
rage
|
||||||
woodpecker-cli
|
woodpecker-cli
|
||||||
jq
|
|
||||||
inputs.terranix.defaultPackage.${system}
|
inputs.terranix.defaultPackage.${system}
|
||||||
(opentofu.withPlugins (p: with p; [
|
(opentofu.withPlugins (p: with p; [
|
||||||
sops # https://registry.terraform.io/providers/carlpett/sops/latest/docs
|
|
||||||
hcloud # https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs
|
hcloud # https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs
|
||||||
]))
|
]))
|
||||||
];
|
];
|
||||||
|
@ -59,11 +58,10 @@
|
||||||
apps = let
|
apps = let
|
||||||
tfCommand = cmd: ''
|
tfCommand = cmd: ''
|
||||||
if [[ -e config.tf.json ]]; then rm -f config.tf.json; fi;
|
if [[ -e config.tf.json ]]; then rm -f config.tf.json; fi;
|
||||||
export TF_CLOUD_TOKEN=$(${pkgs.sops}/bin/sops -d --extract '["tf_cloud_token"]' secrets.enc.yaml)
|
|
||||||
export TF_CLI_CONFIG_FILE="ci.tfrc"
|
export TF_CLI_CONFIG_FILE="ci.tfrc"
|
||||||
cat << EOF > "$TF_CLI_CONFIG_FILE"
|
cat << EOF > "$TF_CLI_CONFIG_FILE"
|
||||||
credentials "app.terraform.io" {
|
credentials "app.terraform.io" {
|
||||||
token = "$TF_CLOUD_TOKEN"
|
token = "$(${sops} -d --extract '["tf_cloud_token"]' .auto.tfvars.enc.yaml)"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
cp ${tfConfig} config.tf.json \
|
cp ${tfConfig} config.tf.json \
|
||||||
|
@ -74,6 +72,10 @@
|
||||||
type = "app";
|
type = "app";
|
||||||
program = toString (pkgs.writers.writeBash name script);
|
program = toString (pkgs.writers.writeBash name script);
|
||||||
}) {
|
}) {
|
||||||
|
# nix run .#encode
|
||||||
|
encode = "${sops} --output-type yaml -e .auto.tfvars.json > .auto.tfvars.enc.yaml";
|
||||||
|
# nix run .#decode
|
||||||
|
decode = "${sops} --output-type json -d .auto.tfvars.enc.yaml > .auto.tfvars.json";
|
||||||
# nix run .#check
|
# nix run .#check
|
||||||
check = tfCommand "validate";
|
check = tfCommand "validate";
|
||||||
# nix run .#apply
|
# nix run .#apply
|
||||||
|
@ -87,7 +89,7 @@
|
||||||
${tfCommand "destroy"}
|
${tfCommand "destroy"}
|
||||||
rm ${toString ./.}/config.tf.json
|
rm ${toString ./.}/config.tf.json
|
||||||
rm ${toString ./.}/*.tfstate*
|
rm ${toString ./.}/*.tfstate*
|
||||||
rm ${toString ./.}/secrets.yaml
|
rm ${toString ./.}/.auto.tfvars.json
|
||||||
rm ${toString ./.}/ci.tfrc
|
rm ${toString ./.}/ci.tfrc
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
tf_cloud_token: ENC[AES256_GCM,data:3vx1n4s7eQxMR2ntOlmnASUuCMxhMMHKLuhf644mNLWbv99aPLsqoUQ+cP01hW/Ra98v3U0C0uYZWfkFn/X8CaVIeu1QPv12D1+XSJB0SJal8NZHJTNVTgzL,iv:W0H4lftTD96/ENjV8tA2a8QqAGI2z/jRvgMtQmaGeB0=,tag:MuXGtyDTbRlNW1xshtCH0g==,type:str]
|
|
||||||
hcloud_api_token: ENC[AES256_GCM,data:HojFdI9gGnO8IkfOREx4bTqrCNBsCDxnUUOmb+VuLMNIEWEifo9tBhm25I+xAogRd0TuYcY4fkARboGL9qsgrw==,iv:18QLpHdNnG82603FxLL38KJaB9sPJ9gj0vmqQWNb1e0=,tag:/6QPhVZy5P5dvP92HUQR6g==,type:str]
|
|
||||||
sops:
|
|
||||||
kms: []
|
|
||||||
gcp_kms: []
|
|
||||||
azure_kv: []
|
|
||||||
hc_vault: []
|
|
||||||
age:
|
|
||||||
- recipient: age1d53yeje0ggysc93uptlpufyhpchyyfs006368j8mw9r20uyeeydse3n7aw
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHa2EzMFlLdTQvMUtzL3FL
|
|
||||||
Rk5JZEdoVkpEQkk3eTR6QkFKY01CaGVwUnpFCm00OWg2bmJ3U2xRMExyeFZ6WVRB
|
|
||||||
UWVjVzY5Y01EOUpDNHYrMFYzVE9GUUEKLS0tIE1LYm80b3V3OUkrNWxQVTRaRGhk
|
|
||||||
TkxRZlprc0I3Q3dQRS82bEd4b1VxTUkKvHZc4c7+9Tsny8w5Cm5L6H+enU1R0tY4
|
|
||||||
9OcNPXGv8II5OJp1eT14U/sNecPbiBaQSeK4xHaRDKbGyqx92DtQ8A==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2024-01-16T21:29:11Z"
|
|
||||||
mac: ENC[AES256_GCM,data:eIoSEDuND1O5XPisSs/kq7N1UsiZMer9+Ok43o+8HwfH/HAoElM/0fXNhKQWcQQVUdwLIQnJZzHEXIJ77Uh5sDsWynj3ihJBhruDPu3FxOXTvRHBcdxU31b3iQGliaChRD19L2GDhsNO2Pfvhpoovsy2PHoFtpqtYt4+7UmcOCw=,iv:Zz1czzz+3Tb5f81o6adhO7eJSSr+ksXhMQwendPAhM0=,tag:bjF2pXTkGxef9+1kKw0FlQ==,type:str]
|
|
||||||
pgp: []
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.8.1
|
|
Loading…
Reference in New Issue