add organization to subject field with terraform's vault provider - terraform

I'm trying to provision a kubernetes cluster by creating all the certificates through vault first. It somehow makes it easy in the context of terraform, because I can insert all this information in the cloudinit config, so I don't have to rely on a node being ready and then transfer data from one to another.
In any case, the problem that I have is that vault_pki_secret_backend_cert doesn't seem to support any change to the subject field except for common_name (https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/pki_secret_backend_cert), whereas kubernetes relies on these types of certificates where the organization is specified. For example:
Subject: O = system:masters, CN = kube-etcd-healthcheck-client
I'm generating these certificates by directly using vault's intermediate certificate, so the private key is in vault. I cannot generate them separately, and I wouldn't want that anyway, because I'm trying to provision basically everything using terraform.
Any ideas how I can get around this issue?

I was able to find out the answer eventually. The only way to do this with terraform/vault seems to be configuring the backend role and add the organization parameter in that role:
https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/cert_auth_backend_role.
For example, you define the role:
resource "vault_pki_secret_backend_role" "etcd_ca_clients" {
depends_on = [ vault_pki_secret_backend_intermediate_set_signed.kube1_etcd_ca ]
backend = vault_mount.kube1_etcd_ca.path
name = "kubernetes-client"
ttl = 3600
allow_ip_sans = true
key_type = "ed25519"
allow_any_name = true
allowed_domains = ["*"]
allow_subdomains = true
organization = [ "system:masters" ]
}
And here you tell vault to generate the certificate based on that role:
resource "vault_pki_secret_backend_cert" "etcd_healthcheck_client" {
for_each = { for k, v in var.kubernetes_servers : k => v if startswith(k, "etcd-") }
depends_on = [vault_pki_secret_backend_role.etcd_ca_clients]
backend = vault_mount.kube1_etcd_ca.path
name = vault_pki_secret_backend_role.etcd_ca_clients.name
common_name = "kube-etcd-healthcheck-client"
}
The limitation makes no sense whatsoever to me, but if you don't a bulk of very different certificates, it's not all too bad and you don't have to repeat a lot of code.

Related

How to get Vault secret through Terraform

I have created the key/secret pair in Vault UI. Trying to get the Vault's secret through Terraform.
Please share thoughts!
You need to define a vault provider, and fetch it as a data object. Here's a simple example:
provider "vault" {
address = "https://my-vault-address.com"
skip_tls_verify = true
token = "xxx"
}
data "vault_generic_secret" "my_secret" {
path = "secret/path/to/mysecret"
}
Then in order to use it:
...
pass = data.vault_generic_secret.my_secret.data["password"]
...

Vault - Assign multiple aliases for one identity group

I've been trying to assign multiple group aliases, meaning, multiple AD groups in our company, into one identity group. So far we've had an identity group for each alias, and we realized that doesn't make sense, as they all carry the same policies.
We are using Terraform in order to maintain and provision our infrastructure.
This is my expected form:
resource "vault_identity_group" "saas-mfi" {
metadata = {
productname = "mfi"
}
name = "saas-mfi"
policies = [
"eaas-key",
"secret-store-mfi"
]
type = "external"
}
resource "vault_identity_group_alias" "alias_1" {
canonical_id = vault_identity_group.saas-mfi.id
mount_accessor = var.org_local_mount_accessor
name = "alias_1"
}
resource "vault_identity_group_alias" "alias_2" {
canonical_id = vault_identity_group.saas-mfi.id
mount_accessor = var.org_local_mount_accessor
name = "alias_2"
}
resource "vault_identity_group_alias" "alias_3" {
canonical_id = vault_identity_group.saas-mfi.id
mount_accessor = var.org_local_mount_accessor
name = "alias_3"
}
When I try to apply this configuration, I get the following error:
Error: Provider produced inconsistent result after apply
Of course, the issue does not stand with the provider. But it seems like one identity group can't have more than one alias to itself. Which is weird, as in the UI, there is a tab for identity groups called "Aliases", in plural.
If anybody has any information regarding this matter, I would really appreciate that.
I was trying to do the same thing but just came across the following paragraph in the documentation for identity:
External group serves as a mapping to a group that is outside of the identity store. External groups can have one (and only one) alias. This alias should map to a notion of group that is outside of the identity store.
From the section on External vs Internal Groups.

Terraform: What is the simplest way to Incrementally add servers to a deployment?

I am a newbie with terraform so donĀ“t laugh :) I want to deploy a number of instances of a server, then add their IPs to a Route53 hosted zone. I will be using Terraform v0.12.24 no chance of 0.14 at the moment.
So far, I have working the "easy", spaghetti approach:
module server: buys and creates a list of servers
module route53: adds route53 records, parameter=aray of ips
main.tf
module "hostedzone" {
source = "./route53"
ncs_domain = var.ncs_domain
}
module "server" {
source = "./server"
name = "${var.ncs_hostname}-${var.ncs_id}"
hcloud_token = var.server_htk
servers = [
{
type = "cx11",
location = "fsn1",
},
{
type = "cx11",
location = "fsn1",
}
]
}
resource "aws_route53_record" "server1-record" {
zone_id = module.hostedzone.zone.zone_id
name = "${var.ncs_hostname}.${var.ncs_domain}"
type = "A"
ttl = "300"
records = module.server.server.*.ipv4_address
}
and the relevant server resource array:
resource "hcloud_server" "apiserver" {
count = length(var.servers)
# Create a server
name = "${var.name}-${count.index}"
# Name server
image = var.image
# Basic image
server_type = var.servers[count.index].type
# Instance type
location = var.servers[count.index].location
}
So if I run terraform apply, I get the server array created. Cool !
Now, I would like to be able to run this module to create and destroy specific servers on demand, like:
initially deploy the platform with one or two servers.
remove one of the initial servers in the array
add new servers
So, how could I use this incrementally, that is, without providing the whole array of servers everytime? Like just adding one to the existing list, or remove other.

Terraform | Retrieve the (client-key) certificate from Cloud SQL

I would like to retrieve the client-key SSL key of cloudsql via Terraform, I was able to retrieve the server-ca and the client-cert via terraform but have no idea how to get the client-key file. TO retrieve the client-cert I have used the below mentioned point: Please look.
resource "google_sql_ssl_cert" "client_cert" {
depends_on = ["google_sql_database_instance.new_instance_sql_master",
"google_sql_user.users"]
common_name = "terraform1"
project = "${var.project_id}"
instance ="${google_sql_database_instance.new_instance_sql_master.name}"
}
Output.tf
output "client_cert" {
value = "${google_sql_ssl_cert.client_cert.0.cert}"
description = "The CA Certificate used to connect to the SQL Instance via
SSL"
}
Please let me know how can I retrieve the client-key private key. i.e server-ca, client-cert and I need client-key via terraform.
In order to get the client private key, use the following snippet with any other parameters you wish to have:
output "client_privkey" {
value = "${google_sql_ssl_cert.client_cert.*.private_key}"
}
For client-certificate: value = "${google_sql_ssl_cert.client_cert.*.cert}"
For server certificate: value = ${google_sql_ssl_cert.client_cert.*.server_ca_cert}"

Terraform aws_lb_ssl_negotiation_policy using AWS Predefined SSL Security Policies

According to: https://www.terraform.io/docs/providers/aws/r/lb_ssl_negotiation_policy.html
You can create a new resource in order to have a ELB SSL Policy so you can customized any Protocol and Ciphers you want. However, I am looking to use Predefined Security Policies set by Amazon as
TLS-1-1-2017-01 or TLS-1-2-2017-01.
http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html
Is there a way to use predefined policies instead of set a new custom policy?
Looking to solve the same problem, I came across this snippet here: https://github.com/terraform-providers/terraform-provider-aws/issues/822#issuecomment-311448488
Basically, you need to create two resources, the aws_load_balancer_policy, and the aws_load_balancer_listener_policy. In the aws_load_balancer_policy you set the policy_attribute to reference the Predefined Security Policy, and then set your listener policy to reference that aws_load_balancer_policy.
I've added a Pull Request to the terraform AWS docs to make this more explicit here, but here's an example snippet:
resource "aws_load_balancer_policy" "listener_policy-tls-1-1" {
load_balancer_name = "${aws_elb.elb.name}"
policy_name = "elb-tls-1-1"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
name = "Reference-Security-Policy"
value = "ELBSecurityPolicy-TLS-1-1-2017-01"
}
}
resource "aws_load_balancer_listener_policy" "ssl_policy" {
load_balancer_name = "${aws_elb.elb.name}"
load_balancer_port = 443
policy_names = [
"${aws_load_balancer_policy.listener_policy-tls-1-1.policy_name}",
]
}
At first glance it appears that this is creating a custom policy that is based off of the predefined security policy, but when you look at what's created in the AWS console you'll see that it's actually just selected the appropriate Predefined Security Policy.
To piggy back on Kirkland's answer, for posterity, you can do the same thing with aws_lb_ssl_negotation_policy if you don't need any other policy types:
resource "aws_lb_ssl_negotiation_policy" "my-elb-ssl-policy" {
name = "my-elb-ssl-policy"
load_balancer = "${aws_elb.my-elb.id}"
lb_port = 443
attribute {
name = "Reference-Security-Policy"
value = "ELBSecurityPolicy-TLS-1-2-2017-01"
}
}
Yes, you can define it. And the default Security Policy ELBSecurityPolicy-2016-08 has covered all ssl protocols you asked for.
Secondly, Protocol-TLSv1.2 covers both policies (TLS-1-1-2017-01 or TLS-1-2-2017-01) you asked for as well.
(http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)
So make sure you enable it with below codes:
resource "aws_lb_ssl_negotiation_policy" "foo" {
...
attribute {
name = "Protocol-TLSv1.2"
value = "true"
}
}

Resources