Skip to content

Commit

Permalink
Support CA certificates in bundles
Browse files Browse the repository at this point in the history
  • Loading branch information
ThetaSinner committed Dec 17, 2019
1 parent 90114cf commit f9b5697
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 13 deletions.
3 changes: 1 addition & 2 deletions example/data_source/main.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

provider "keystore" {
path = "${path.module}/../out"
}
Expand All @@ -8,5 +7,5 @@ data "keystore_pkcs12_bundle" "my-bundle" {
}

output "my-bundle" {
value = "${data.keystore_pkcs12_bundle.my-bundle.bundle}"
value = data.keystore_pkcs12_bundle.my-bundle.bundle
}
63 changes: 55 additions & 8 deletions example/resource/main.tf
Original file line number Diff line number Diff line change
@@ -1,34 +1,81 @@
resource "tls_private_key" "example" {
resource "tls_private_key" "example-ca" {
algorithm = "RSA"
rsa_bits = 2048
}

resource "tls_self_signed_cert" "example_certificate" {
key_algorithm = "${tls_private_key.example.algorithm}"
private_key_pem = "${tls_private_key.example.private_key_pem}"
resource "tls_self_signed_cert" "example-ca" {
key_algorithm = tls_private_key.example-ca.algorithm
private_key_pem = tls_private_key.example-ca.private_key_pem

subject {
common_name = "example.com"
common_name = "example CA"
organization = "EphyraSoftware"
}

dns_names = ["example.com"]
dns_names = ["exampleca"]

validity_period_hours = 2190 // Three months

is_ca_certificate = true

allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth"
]
}

resource "tls_private_key" "example" {
algorithm = "RSA"
rsa_bits = 2048
}

resource "tls_cert_request" "example" {
key_algorithm = tls_private_key.example-ca.algorithm
private_key_pem = tls_private_key.example.private_key_pem

subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
}

resource "tls_locally_signed_cert" "example" {
cert_request_pem = tls_cert_request.example.cert_request_pem
ca_key_algorithm = tls_private_key.example-ca.algorithm
ca_private_key_pem = tls_private_key.example-ca.private_key_pem
ca_cert_pem = tls_self_signed_cert.example-ca.cert_pem

validity_period_hours = 12

allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
}

provider "keystore" {
path = "${path.module}/../out"
}

output "cert_pem" {
value = tls_locally_signed_cert.example.cert_pem
}

output "key_pem" {
value = tls_private_key.example.private_key_pem
}

output "ca_certs" {
value = tls_self_signed_cert.example-ca.cert_pem
}

resource "keystore_pkcs12_bundle" "my-bundle" {
name = "my-bundle-name"
cert_pem = "${tls_self_signed_cert.example_certificate.cert_pem}"
key_pem = "${tls_private_key.example.private_key_pem}"
cert_pem = tls_locally_signed_cert.example.cert_pem
key_pem = tls_private_key.example.private_key_pem
ca_certs = [
tls_self_signed_cert.example-ca.cert_pem
]
}
27 changes: 25 additions & 2 deletions impl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"software.sslmate.com/src/go-pkcs12"
)

func CreateBundle(certPEM string, keyPEM string, outputPath string, name string) error {
func CreateBundle(certPEM string, keyPEM string, caCertsPEM []string, outputPath string, name string) error {
block, _ := pem.Decode([]byte(certPEM))
if block == nil || block.Type != "CERTIFICATE" {
return errors.New("could not decode public certificate")
Expand All @@ -35,11 +35,26 @@ func CreateBundle(certPEM string, keyPEM string, outputPath string, name string)
return errors.New("could not parse private key")
}

caCerts := make([]*x509.Certificate, len(caCertsPEM))
for i, cert := range caCertsPEM {
block, _ := pem.Decode([]byte(cert))
if block == nil || block.Type != "CERTIFICATE" {
return errors.New("could not decode CA certificate")
}

caCert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return errors.New("could not parse CA certificate")
}

caCerts[i] = caCert
}

result, err := pkcs12.Encode(
rand.Reader,
privateKey,
publicKey,
[]*x509.Certificate{},
caCerts,
pkcs12.DefaultPassword,
)

Expand All @@ -55,3 +70,11 @@ func CreateBundle(certPEM string, keyPEM string, outputPath string, name string)

return nil
}

func SliceOfString(slice []interface{}) []string {
result := make([]string, len(slice), len(slice))
for i, s := range slice {
result[i] = s.(string)
}
return result
}
9 changes: 8 additions & 1 deletion resource_pkcs12_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ func pkcsBundle() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"ca_certs": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"bundle": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Expand All @@ -44,8 +50,9 @@ func pkcsBundleCreate(d *schema.ResourceData, m interface{}) error {

certPEM := d.Get("cert_pem").(string)
keyPEM := d.Get("key_pem").(string)
caCerts := d.Get("ca_certs").(*schema.Set).List()

err := impl.CreateBundle(certPEM, keyPEM, outputPath, name)
err := impl.CreateBundle(certPEM, keyPEM, impl.SliceOfString(caCerts), outputPath, name)
if err != nil {
return err
}
Expand Down

0 comments on commit f9b5697

Please sign in to comment.