Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

certificate_p12 without a password #32

Closed
mkg2 opened this issue Mar 3, 2019 · 13 comments · Fixed by #35
Closed

certificate_p12 without a password #32

mkg2 opened this issue Mar 3, 2019 · 13 comments · Fixed by #35

Comments

@mkg2
Copy link

mkg2 commented Mar 3, 2019

Hello,

I am trying to pass 'certificate_p12' attribute to azure web application firewall Resource. Looks like it is mandatory to have a password while adding ssl_certificate into azure WAF.
acme Resources

resource "tls_private_key" "private_key" {
    algorithm = "RSA"
}
resource "acme_registration" "reg" {
    account_key_pem = "${tls_private_key.private_key.private_key_pem}"
}
resource "acme_certificate" "certificate" {
    account_key_pem           = "${acme_registration.reg.account_key_pem}"
    common_name               = "mkg2test.com"
    subject_alternative_names = ["www.mkg2test.com"]
    dns_challenge {
        provider = "azure"
        config {
            AZURE_RESOURCE_GROUP = "mkg2test"
        }
    }
}

acme module output

output "certificate" {
  value = "${acme_certificate.certificate.certificate_p12}"
}

Calling WAF Resource

module "waf-dev" {
    source      = "./modules/waf"
    prefix      = "mkg2"
    location    = "${var.default_location}"
    certificate = "${module.ssl.certificate}" //Data from above output
    providers = {
        "azurerm" = "azurerm.azure"
    }
}

WAF Resource

resource "azurerm_application_gateway" "main" {
    name                = "${var.prefix}-agw"
    resource_group_name = "${azurerm_resource_group.main.name}"
    location            = "${var.location}"
    sku {
        name     = "WAF_Medium"
        tier     = "WAF"
        capacity = 2
    }    
    gateway_ip_configuration {
        name      = "${var.prefix}-gwip"
        subnet_id = "${azurerm_subnet.main.id}"
    }
    frontend_ip_configuration {
        name                 = "${var.prefix}-frontEndIpConf"
        public_ip_address_id = "${azurerm_public_ip.main.id}"
    }    
    frontend_port {
        name = "${var.prefix}-https"
        port = 443
    }
    ssl_certificate {
        name     = "${var.prefix}-cert"
        data     = "${var.certificate}"
        password    = ""
    }
.........
.......
    waf_configuration {
        firewall_mode    = "detection"
        rule_set_type    = "OWASP"
        rule_set_version = "3.0"
        enabled          = "true"
    }
}

Error


1 error(s) occurred:


* module.waf-dev.azurerm_application_gateway.main: 1 error(s) occurred:


* azurerm_application_gateway.main: Error Creating/Updating Application Gateway "main" (Resource Group "mkg2test"): network.ApplicationGatewaysClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="ApplicationGatewaySslCertificateInvalidData" Message="Data or Password for certificate /subscriptions/****/resourceGroups/mkg2test/providers/Microsoft.Network/applicationGateways/mkg2test-agw/sslCertificates/mkg2test-cert is invalid." Details=[]

Any advise or guidance would be greatly appreciated..

Thanks,
mkg

@vancluever
Copy link
Owner

@mkg2 I was having issues getting people to actually tell me if this was actually working on Azure or not. Guess it wasn't 😕

Would you be able to save the bundle to a local file, actually set a password on it and then try it, to see if it worked? If it does, I might just update the code so that it has a static password of "changeit" or something, just basically to satisfy that requirement and still communicate that we effectively don't set a password on the P12 file.

@JimPaine
Copy link
Contributor

JimPaine commented Mar 4, 2019

It might not be related, but it would be good to validate before I create a new issue, but I found that the base64 encoded value in certificate_p12 was not valid. I had to add "==" to the end of it to get mine to work. And another time just a single "="

Which is a bit of a pain. I plan to do a bit more digging but might help you move forward.

resource "azurerm_key_vault_secret" "cert" {
  name      = "cert"
  value     = "${acme_certificate.demo.certificate_p12}=="
  key_vault_id = "${azurerm_key_vault.demo.id}"
  content_type = "application/x-pkcs12"
}

A better workaround would be to use a local-exec provisioner to use openssl to recreate a pfx

@vancluever
Copy link
Owner

@JimPaine that's the padding on the base64 encoding, which is good to know. I'll make sure that's in as well.

So did it actually work for you without a password?

@JimPaine
Copy link
Contributor

JimPaine commented Mar 4, 2019

Yea I just mentioned as it looked like your error mentioned it could have been an issue with the data or the password. But I do have it working with an Azure function with no password.

@vancluever
Copy link
Owner

@mkg2 can you test with the padding fix @JimPaine has above so that we can validate?

@JimPaine
Copy link
Contributor

JimPaine commented Mar 4, 2019

Just in case this issue is not related to the padding issue I have raised a new issue here along with my findings. #33

@vancluever
Copy link
Owner

@JimPaine thanks! I've replied in that thread as well.

@piizei
Copy link

piizei commented Mar 5, 2019

I can confirm that it does not work with Azure WAF without password (padding or not). +1 for 'changeit'.

@mkg2
Copy link
Author

mkg2 commented Mar 5, 2019

Unfortunately, it is not working as expected.

Point 1:

I have tried to store the certificate_p12 to a local file and ended up with an invalid text file.

Terraform code

resource "local_file" "pkcs12" {
    content     = "${acme_certificate.certificate.certificate_p12}=="
    filename = "/tmp/Cert_direct.p12"
}

Certificate verification

I am expecting a base64 encoded data file in linux but below file is in text format.

$ file /tmp/Cert_direct.p12
Cert_direct.p12: ASCII text, with very long lines, with no line terminators
$

Verification with keytool not working as well.

$ keytool -list -v -keystore /tmp/Cert_direct.p12 -storetype PKCS12
keytool error: java.io.IOException: toDerInputStream rejects tag type 77
java.io.IOException: toDerInputStream rejects tag type 77
        at sun.security.util.DerValue.toDerInputStream(DerValue.java:881)
        at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1939)
        at java.security.KeyStore.load(KeyStore.java:1445)
        at sun.security.tools.keytool.Main.doCommands(Main.java:827)
        at sun.security.tools.keytool.Main.run(Main.java:368)
        at sun.security.tools.keytool.Main.main(Main.java:361)

Point 2:

I have uploaded 'certificate_p12' directlry to azure vault.

Terraform code

resource "azurerm_key_vault_secret" "cert" {
    name      = "cert"
    value     = "${acme_certificate.certificate.certificate_p12}=="
    key_vault_id = "${data.azurerm_key_vault.main.id}"
    content_type = "application/x-pkcs12"
}

Then I tried to download the file from azure web console as certificate.

File download error
Failed to download the file. Error details: Bad request 400 Date uri content is not properly encoded. For binary type, please encode it with base64 encoding

Point 3:

Only workaround so far is to create the pkcs12 bundle with local-exec.

resource "local_file" "private_key_pem" {
    content     = "${acme_certificate.certificate.private_key_pem}"
    filename = "/tmp/key.pem"
}
resource "local_file" "certificate_pem" {
    content     = "${acme_certificate.certificate.certificate_pem}"
    filename = "/tmp/cert.pem"
}
resource "null_resource" "main" {
    triggers {
        build_number = "${timestamp()}"
    }
    provisioner "local-exec" {
        command = "openssl pkcs12 -export -out /tmp/Cert.p12 -in /tmp/cert.pem -inkey /tmp/key.pem -passout pass:abcd"
    }
}

Cerificate verification

$ file Cert.p12
Cert.p12: data
$

Verification with keytool

$ keytool -list -v -keystore /tmp/Cert.p12 -storetype PKCS12
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry
....
...

@JimPaine
Copy link
Contributor

JimPaine commented Mar 5, 2019

@mkg2 @piizei I can confirm this is the case.

Seeing that it not consistent across Azure resources, I think it would be better to create a new optional argument, something like "p12_certificate_password" which defaults to an empty string.

If you both agree I am happy to make the changes and create a PR later today. Only seems fair @vancluever, seeing that it is Azure based issues :)

@piizei
Copy link

piizei commented Mar 7, 2019

@JimPaine are you working on the password? I was just wondering should I wait or implement the workaround suggested by @mkg2 ?

@JimPaine
Copy link
Contributor

JimPaine commented Mar 7, 2019

Sorry @piizei, picking it up today, I had a few things come up that I needed to sort. Still waiting on #34 to be merged in as well, so it might be worth doing the work around as that will also workaround that issue as well.

Work in progress is here if you want to build and run yourself
https://github.com/JimPaine/terraform-provider-acme/tree/p12-cert-password

@vancluever
Copy link
Owner

Hey all, this has now been merged and should be going out for release early next week. Thanks @JimPaine for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants