There are two ways of defining the KU and EKU for certificates generated by the step toolchain; both require the use of templates. Here’s a basic example of the default template generating an X.509 certificate with some listed settings for Key Usage and Extended Key Usage:

{
    "subject": {{ toJson .Subject }},
    "sans": {{ toJson .SANs }},
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
    "keyUsage": ["keyEncipherment", "digitalSignature"],
{{- else }}
    "keyUsage": ["digitalSignature"],
{{- end }}
    "extKeyUsage": ["serverAuth", "clientAuth"]
}

Hard-Coded Values

If you simply need all certificates generated by a given provisioner to have digitalSignature, keyEncipherment, keyAgreement, and serverAuth abilities (eg. requirements for OpenVPN servers), your template could be as simple as the following:

{
  "subject": {{ toJson .Subject }},
  "sans": {{ toJson .SANs }},
  "keyUsage": ["digitalSignature", "keyEncipherment", "keyAgreement"],
  "extKeyUsage": ["serverAuth"]
}

From here, you can create a new provisioner (or update an existing provisioner) that uses this template to sign certificates:

$ step ca provisioner add <name> --type JWK --create \
    --x509-template <template_file>

Passing Values with Variables

If you would like anyone with access to a given provisioner to request any KU/EKU of their choosing, you can use variables and the --set command to allow users to define the desired settings. The following template uses two user-based variables:

{
    "subject": {{ toJson .Subject }},
    "sans": {{ toJson .SANs }},
{{- if .Insecure.User.keyUsage }}
    "keyUsage": {{ toJson .Insecure.User.keyUsage }},
{{- else }}
    "keyUsage": ["digitalSignature"],
{{- end }}
{{- if .Insecure.User.extKeyUsage }}
    "extKeyUsage": {{ toJson .Insecure.User.extKeyUsage }},
{{- else }}
    "extKeyUsage": ["serverAuth", "clientAuth"]
{{- end }}
}

This template will check if the user has defined the keyUsage and extendedKeyUsage fields when requesting a certificate. If they did, then the certificate will use these values instead of the ones listed as defaults on the template.

Once this template is in place, a user can pass the --set flags to specify the keyUsage and extendedKeyUsage fields when requesting a certificate:

$ step ca certificate "Test Certificate" test.crt test.key \
    --provisioner <name> \
    --set keyUsage='["digitalSignature", "keyAgreement"]' \
    --set extKeyUsage='["clientAuth"]'