cloudflare / cfssl

CFSSL: Cloudflare's PKI and TLS toolkit
https://cfssl.org/
BSD 2-Clause "Simplified" License
8.76k stars 1.11k forks source link

policy violation error when creating intermediate CA with profile intermediate #657

Open andrewmgee opened 8 years ago

andrewmgee commented 8 years ago

From #652, when issuing the cli command:

cfssl sign -ca ca.pem -ca-key ca-key.pem -profile intermediate -config config.json intermediate.csr | cfssljson -bare intermediate

Still results in the same error "local signer policy disallows issuing CA certificate"

intermediate config json

{
    "signing": {
        "default": {
            "expiry": 43800h"
        },
        "profiles": {
            "intermediate": {
                    "usages": [
                        "signing",
                        "key encipherment",
                        "cert sign",
                        "crl sign"
                    ],
                    "expiry": "43800h",
                    "ca_constraint": {
                    "is_ca": true,
                    "max_path_len": 0,
                    "max_path_len_zero": true
                }
                }
        }
    }
}
lziest commented 8 years ago

ok, if that's your json file, it is malformed. look at line 4, use jq to check.

andrewmgee commented 8 years ago

sorry, mistype when I copy/paste. It was however valid when I ran the cli command.

lziest commented 8 years ago

I can't reproduce, are you using the tip of cfssl? Build cfssl from current master and try again.

andrewmgee commented 8 years ago

just tried re-building, same error

lziest commented 8 years ago

cfssl sign -ca ca.pem -ca-key ca-key.pem -profile intermediate -config config.json intermediate.csr -loglevel=0 paste the output

andrewmgee commented 8 years ago
2016/08/19 17:33:58 [DEBUG] loading configuration file from config.json
2016/08/19 17:33:58 [DEBUG] parse expiry in profile
2016/08/19 17:33:58 [DEBUG] expiry is valid
2016/08/19 17:33:58 [DEBUG] parse expiry in profile
2016/08/19 17:33:58 [DEBUG] expiry is valid
2016/08/19 17:33:58 [DEBUG] validating configuration
2016/08/19 17:33:58 [DEBUG] validate local profile
2016/08/19 17:33:58 [DEBUG] profile is valid
2016/08/19 17:33:58 [DEBUG] validate local profile
2016/08/19 17:33:58 [DEBUG] profile is valid
2016/08/19 17:33:58 [DEBUG] configuration ok
2016/08/19 17:33:58 [DEBUG] validating configuration
2016/08/19 17:33:58 [DEBUG] validate local profile
2016/08/19 17:33:58 [DEBUG] profile is valid
2016/08/19 17:33:58 [DEBUG] validate local profile
2016/08/19 17:33:58 [DEBUG] profile is valid
2016/08/19 17:33:58 [DEBUG] Loading CA: ../root-ca/ca.pem
2016/08/19 17:33:58 [DEBUG] Loading CA key: ../root-ca/ca-key.pem
2016/08/19 17:33:58 [DEBUG] validating configuration
2016/08/19 17:33:58 [DEBUG] validate local profile
2016/08/19 17:33:58 [DEBUG] profile is valid
2016/08/19 17:33:58 [DEBUG] validate local profile
2016/08/19 17:33:58 [DEBUG] profile is valid
2016/08/19 17:33:58 [ERROR] local signer policy disallows issuing CA certificate
{"code":5300,"message":"Policy violation request"}
lziest commented 8 years ago

We can't reproduce. You can literally locate the error message to one line of code. If you find the problem, patches are welcomed.

emmaly commented 8 years ago

I had what I thought was this exact problem, but it turned out that my root CA's config.json file used "max_path_len_zero":true where it should have not been true. My intermediate CA resulted in being an intermediate CA that was unable to effectively sign any CA certificates. (For my use case, it's necessary for me to have a root [controlled by me], then an intermediate [controlled by me], then another intermediate [controlled by an internal group, not solely me], then the end certs). In my case I set "max_path_len":0 for both the root CA's config.json and the intermediate CA's config.json, but used "max_path_len_zero":false for the root CA's config.json (which means it was applied to the intermediate when the intermediate was being signed by the root) and then "max_path_len_zero":true for the intermediate CA's config.json so its children couldn't produce any more CAs. I don't know if this is what you're coming across here, but maybe it'll help.

jacobcase commented 7 years ago

Possibly related.

If you download the prebuilt binary from pkg.cfssl.org for OSX, and you create an intermediate where you're granting it permission to function as a CA, it correctly creates an intermediate with that privilege. However, if you download the same version for Linux and mint an intermediate certificate using the same configuration, it does not have the ability to function as a CA.

Both are the same version, but the Linux one is built with Go 1.6, while the OSX one is built with Go 1.7, so to test if that's somehow responsible, I built the Linux version with Go 1.7 and it correctly created an intermediate with the CA capability.

I use the following configuration:

{
    "signing": {
        "default": {
            "expiry": "2160h"
        },
        "profiles": {
            "peer": {
                "expiry": "720h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "client auth",
                    "server auth"
                ]
            },
            "client": {
              "expiry": "720h",
              "usages": [
                "signing",
                "key encipherment",
                "client auth"
              ]
            },
            "intermediate": {
              "expiry": "720h",
              "usages": [
                "cert sign",
                "crl sign"
              ],
              "ca_constraint": {"is_ca": true}
            }

        }
    }
}

I've been inspecting them with: openssl x509 -in intermediate-ca/intermediate-ca.pem -noout -text and looking for the section

            X509v3 Basic Constraints: critical
                CA:TRUE

Assuming this can be replicated, I wonder if this warrants an issue to be opened recommending cfssl being built with Go 1.7, and also built the pre-built binary with 1.7 for Linux.

chjohnst commented 7 years ago

I am seeing a similar issue with the 1.6 version you can download from you guys, my configs below. Essentially my goal is to create an intermediate CA with a pathlen of 0 so it can just issue user certs.

Config: { "signing": { "default": { "expiry": "87600h" }, "profiles": { "intermediate": { "expiry": "87600h", "usages": [ "key encipherment", "signing", "cert sign", "crl sign" ], "ca_constraint": { "is_ca": true, "max_path_len": 0, "max_path_len_zero": true } } } } }

Commands:

intermediate: cfssl genkey -initca intermediate/intermediate.json | cfssljson -bare intermediate/intermediate cfssl sign -ca root/root.pem -ca-key root/root-key.pem -config config.json -profile intermediate intermediate/intermediate.csr | cfssljson -bare intermediate/intermediate

Intermediate extensions: X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment, Certificate Sign, CRL Sign X509v3 Basic Constraints: critical CA:FALSE

maikzumstrull commented 7 years ago

Looks like the last two commenters are on to something - I'm seeing a very similar issue: cfssl from Homebrew creates a broken (non-CA) cert when asked to produce an intermediate, same version installed with "go get" works fine.

The specific problem appears to happen when producing the CSR for the intermediate. This part:

        Requested Extensions:
            X509v3 Basic Constraints:
                CA:TRUE, pathlen:1

is missing from the CSR file when using cfssl from Homebrew. "cfssl sign" then produces a cert with CA:FALSE.

msvechla commented 7 years ago

I had the exact same issue. I was able to fix the CA:FALSE by changing the following block in the ca-config.json:

faulty:

"intermediate": {
        "usages": [
          "cert sign",
          "crl sign"
        ],
        "expiry": "262800h",
        "ca_constraint": {
            "is_ca": true,
            "max_path_len": 1
        }
      },

correct:

"intermediate": {
        "usages": [
          "cert sign",
          "crl sign"
        ],
        "expiry": "262800h",
        "is_ca": true,
        "max_path_len": 1
      },

Maybe this also fixes it for you.

EDIT: However I am unable to create a certificate with pathlen: 0, no matter what combination I am trying. EDIT2: After building cfssl from source with go 1.6 on linux in docker it works on my centos machine to create a certificate with max_path_len: 0. So I assume the binary provided on https://pkg.cfssl.org/ has a bug

akemner commented 7 years ago

@msvechla i'm running into the exact same issue. i can't create a certificate with pathlen: 0

i'm planning to do some further testing on this myself but curious if when you built from source did you build from the 1.2.0 tag or from master?

https://github.com/cloudflare/cfssl/releases/tag/1.2.0

den-is commented 6 years ago

Was fighting same issue from cfssl 1.2 installed from homebrew.

macos High Siera 10.13.2
cfssl version
Version: 1.2.0
Revision: dev
Runtime: go1.9.2

Wasn't able to create intermediate with "cfssl sign ... intermediate.csr" - output was cert with CA:FALSE.

Issue was fixed with go get -u ... manual install.

Now I have functional intermediate CA, with pathlen=0

alethenorio commented 6 years ago

I just ran into the same issue myself using the latest release binary download from https://pkg.cfssl.org/. Getting the latest development version (go get -u ....) as suggested by @den-is solved the problem.

flyinprogrammer commented 6 years ago

@cbroglie I see you've been the one cutting these releases. Is there any chance we could get a new release of binaries to https://pkg.cfssl.org/ ?

After embarrassingly losing a day of my life to this bug, and now learning a lot about certificates and certificate chains, I can confirm the latest development version has this particular bug fixed as well. It is definitely broken in 1.2

esolitos commented 5 years ago

Following after having the same issue, spent quite some hours trying to understand why ca_constraint were not working until I encountered this issue and figure i still needed to use the "old" is_ca option.

Not sure if the issue is that all the online documentation points to the first ca_constraint or if i got the wrong version or what, but definitely was not easy to figure.

Installed cfssl via: pkg.cfssl.org version 1.2 linux amd64.

    $ cfssl version
    Version: 1.2.0
    Revision: dev
    Runtime: go1.6

    $ lsb_release -a 
    No LSB modules are available.
    Distributor ID: Ubuntu
    Description:    Pop!_OS 18.10
    Release:    18.10
    Codename:   cosmic
devinrsmith commented 5 years ago

I ran into this issue just now. It seems like the the -profile flag is not working for me, and it was falling back to the "default" profile. I'm not sure if it's a parser issue, code logic, or if I'm invoking the cfssl sign command incorrectly.

I've verified that setting the same parameters into the "default" profile allows my sign command to successfully complete - so I know the ca_constraint is specified correctly.

$ cfssl version
Version: 1.3.4
Revision: dev
Runtime: go1.12.7