2015-05-15 16:13:05 +00:00
package pki
import (
2018-01-08 18:31:38 +00:00
"context"
2016-06-22 20:08:24 +00:00
"crypto/x509"
2015-05-15 16:13:05 +00:00
"fmt"
2015-12-01 04:49:11 +00:00
"strings"
2015-05-15 16:13:05 +00:00
"time"
2018-02-16 22:19:34 +00:00
"github.com/hashicorp/errwrap"
2019-04-13 07:44:06 +00:00
"github.com/hashicorp/vault/sdk/framework"
2019-05-09 15:43:11 +00:00
"github.com/hashicorp/vault/sdk/helper/certutil"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/parseutil"
"github.com/hashicorp/vault/sdk/logical"
2015-05-15 16:13:05 +00:00
)
2016-01-28 20:18:07 +00:00
func pathListRoles ( b * backend ) * framework . Path {
return & framework . Path {
Pattern : "roles/?$" ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
logical . ListOperation : b . pathRoleList ,
} ,
2016-06-20 23:51:04 +00:00
HelpSynopsis : pathListRolesHelpSyn ,
HelpDescription : pathListRolesHelpDesc ,
2016-01-28 20:18:07 +00:00
}
}
2015-05-15 16:13:05 +00:00
func pathRoles ( b * backend ) * framework . Path {
return & framework . Path {
2015-08-21 07:56:13 +00:00
Pattern : "roles/" + framework . GenericNameRegex ( "name" ) ,
2015-05-15 16:13:05 +00:00
Fields : map [ string ] * framework . FieldSchema {
2019-02-14 17:42:44 +00:00
"backend" : & framework . FieldSchema {
Type : framework . TypeString ,
Description : "Backend Type" ,
} ,
2015-05-15 16:13:05 +00:00
"name" : & framework . FieldSchema {
Type : framework . TypeString ,
2015-06-18 14:44:02 +00:00
Description : "Name of the role" ,
2015-05-15 16:13:05 +00:00
} ,
2015-08-27 19:24:37 +00:00
"ttl" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeDurationSecond ,
2015-08-27 19:24:37 +00:00
Description : ` The lease duration if no specific lease duration is
requested . The lease duration controls the expiration
of certificates issued by this backend . Defaults to
the value of max_ttl . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "TTL" ,
} ,
2015-08-27 19:24:37 +00:00
} ,
"max_ttl" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeDurationSecond ,
2015-08-27 19:24:37 +00:00
Description : "The maximum allowed lease duration" ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Max TTL" ,
} ,
2015-05-15 16:13:05 +00:00
} ,
"allow_localhost" : & framework . FieldSchema {
2015-06-18 14:44:02 +00:00
Type : framework . TypeBool ,
Default : true ,
Description : ` Whether to allow "localhost" as a valid common
name in a request ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Value : true ,
} ,
2015-05-15 16:13:05 +00:00
} ,
2015-12-01 04:49:11 +00:00
"allowed_domains" : & framework . FieldSchema {
2017-12-11 18:13:35 +00:00
Type : framework . TypeCommaStringSlice ,
2015-06-18 14:44:02 +00:00
Description : ` If set , clients can request certificates for
2015-12-01 04:49:11 +00:00
subdomains directly beneath these domains , including
the wildcard subdomains . See the documentation for more
2017-12-11 18:13:35 +00:00
information . This parameter accepts a comma - separated
string or list of domains . ` ,
2015-10-02 16:22:02 +00:00
} ,
2020-07-08 16:52:25 +00:00
"allowed_domains_template" : & framework . FieldSchema {
Type : framework . TypeBool ,
Description : ` If set , Allowed domains can be specified using identity template policies .
Non - templated domains are also permitted . ` ,
Default : false ,
} ,
2015-12-01 04:49:11 +00:00
"allow_bare_domains" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2015-10-02 16:22:02 +00:00
Description : ` If set , clients can request certificates
2015-12-01 04:49:11 +00:00
for the base domains themselves , e . g . "example.com" .
This is a separate option as in some cases this can
be considered a security threat . ` ,
2015-05-15 16:13:05 +00:00
} ,
"allow_subdomains" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2015-06-18 14:44:02 +00:00
Description : ` If set , clients can request certificates for
subdomains of the CNs allowed by the other role options ,
including wildcard subdomains . See the documentation for
more information . ` ,
2015-05-15 16:13:05 +00:00
} ,
2017-05-01 14:40:18 +00:00
"allow_glob_domains" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2017-05-01 14:40:18 +00:00
Description : ` If set , domains specified in "allowed_domains"
can include glob patterns , e . g . "ftp*.example.com" . See
the documentation for more information . ` ,
} ,
2015-05-15 16:13:05 +00:00
"allow_any_name" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2015-06-18 14:44:02 +00:00
Description : ` If set , clients can request certificates for
any CN they like . See the documentation for more
information . ` ,
2015-05-15 16:13:05 +00:00
} ,
2015-08-20 21:33:37 +00:00
"enforce_hostnames" : & framework . FieldSchema {
Type : framework . TypeBool ,
2015-11-16 15:10:03 +00:00
Default : true ,
2015-08-20 21:33:37 +00:00
Description : ` If set , only valid host names are allowed for
2015-11-16 15:10:03 +00:00
CN and SANs . Defaults to true . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Value : true ,
} ,
2015-08-20 21:33:37 +00:00
} ,
2015-05-15 16:13:05 +00:00
"allow_ip_sans" : & framework . FieldSchema {
2015-06-18 14:44:02 +00:00
Type : framework . TypeBool ,
Default : true ,
Description : ` If set , IP Subject Alternative Names are allowed .
Any valid IP is accepted . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Allow IP Subject Alternative Names" ,
Value : true ,
} ,
2015-05-15 16:13:05 +00:00
} ,
2018-06-15 19:32:25 +00:00
"allowed_uri_sans" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , an array of allowed URIs to put in the URI Subject Alternative Names .
Any valid URI is accepted , these values support globbing . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Allowed URI Subject Alternative Names" ,
} ,
2018-06-15 19:32:25 +00:00
} ,
2018-02-16 22:19:34 +00:00
"allowed_other_sans" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
2018-10-08 13:51:43 +00:00
Description : ` If set, an array of allowed other names to put in SANs. These values support globbing and must be in the format <oid>;<type>:<value>. Currently only "utf8" is a valid type. All values, including globbing values, must use this syntax, with the exception being a single "*" which allows any OID and any value (but type must still be utf8). ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Allowed Other Subject Alternative Names" ,
} ,
2018-02-16 22:19:34 +00:00
} ,
2018-06-05 03:18:39 +00:00
"allowed_serial_numbers" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set, an array of allowed serial numbers to put in Subject. These values support globbing. ` ,
} ,
2015-05-15 16:13:05 +00:00
"server_flag" : & framework . FieldSchema {
2015-06-18 14:44:02 +00:00
Type : framework . TypeBool ,
Default : true ,
2015-08-29 13:03:02 +00:00
Description : ` If set , certificates are flagged for server auth use .
2015-06-18 14:44:02 +00:00
Defaults to true . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Value : true ,
} ,
2015-05-15 16:13:05 +00:00
} ,
"client_flag" : & framework . FieldSchema {
2015-06-18 14:44:02 +00:00
Type : framework . TypeBool ,
Default : true ,
2015-08-29 13:03:02 +00:00
Description : ` If set , certificates are flagged for client auth use .
2015-06-18 14:44:02 +00:00
Defaults to true . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Value : true ,
} ,
2015-05-15 16:13:05 +00:00
} ,
"code_signing_flag" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2015-06-18 14:44:02 +00:00
Description : ` If set , certificates are flagged for code signing
use . Defaults to false . ` ,
2015-05-15 16:13:05 +00:00
} ,
2015-10-02 15:55:30 +00:00
"email_protection_flag" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2015-08-29 13:03:02 +00:00
Description : ` If set , certificates are flagged for email
protection use . Defaults to false . ` ,
} ,
2015-05-15 16:13:05 +00:00
"key_type" : & framework . FieldSchema {
2015-06-18 14:44:02 +00:00
Type : framework . TypeString ,
Default : "rsa" ,
Description : ` The type of key to use ; defaults to RSA . "rsa"
and "ec" are the only valid values . ` ,
2019-02-14 17:42:44 +00:00
AllowedValues : [ ] interface { } { "rsa" , "ec" } ,
2015-05-15 16:13:05 +00:00
} ,
"key_bits" : & framework . FieldSchema {
2015-06-18 14:44:02 +00:00
Type : framework . TypeInt ,
Default : 2048 ,
Description : ` The number of bits to use . You will almost
certainly want to change this if you adjust
the key_type . ` ,
2015-05-15 16:13:05 +00:00
} ,
2015-10-09 17:45:17 +00:00
2016-06-22 20:08:24 +00:00
"key_usage" : & framework . FieldSchema {
2017-12-11 18:13:35 +00:00
Type : framework . TypeCommaStringSlice ,
Default : [ ] string { "DigitalSignature" , "KeyAgreement" , "KeyEncipherment" } ,
Description : ` A comma - separated string or list of key usages ( not extended
2016-06-22 20:08:24 +00:00
key usages ) . Valid values can be found at
https : //golang.org/pkg/crypto/x509/#KeyUsage
-- simply drop the "KeyUsage" part of the name .
To remove all key usages from being set , set
2017-12-11 18:13:35 +00:00
this value to an empty list . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Value : "DigitalSignature,KeyAgreement,KeyEncipherment" ,
} ,
2016-06-22 20:08:24 +00:00
} ,
2018-06-15 22:20:43 +00:00
"ext_key_usage" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Default : [ ] string { } ,
Description : ` A comma - separated string or list of extended key usages . Valid values can be found at
https : //golang.org/pkg/crypto/x509/#ExtKeyUsage
-- simply drop the "ExtKeyUsage" part of the name .
To remove all key usages from being set , set
this value to an empty list . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Extended Key Usage" ,
} ,
2018-06-15 22:20:43 +00:00
} ,
2018-06-01 13:13:54 +00:00
"ext_key_usage_oids" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` A comma-separated string or list of extended key usage oids. ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Extended Key Usage OIDs" ,
} ,
2018-06-01 13:13:54 +00:00
} ,
2015-10-09 17:45:17 +00:00
"use_csr_common_name" : & framework . FieldSchema {
2015-11-12 16:24:32 +00:00
Type : framework . TypeBool ,
2015-11-16 15:10:03 +00:00
Default : true ,
2015-10-09 17:45:17 +00:00
Description : ` If set , when used with a signing profile ,
the common name in the CSR will be used . This
does * not * include any requested Subject Alternative
2015-11-16 15:10:03 +00:00
Names . Defaults to true . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Use CSR Common Name" ,
Value : true ,
} ,
2015-10-09 17:45:17 +00:00
} ,
2017-01-23 17:44:45 +00:00
2017-03-15 18:38:18 +00:00
"use_csr_sans" : & framework . FieldSchema {
Type : framework . TypeBool ,
Default : true ,
Description : ` If set , when used with a signing profile ,
the SANs in the CSR will be used . This does * not *
include the Common Name ( cn ) . Defaults to true . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Use CSR Subject Alternative Names" ,
Value : true ,
} ,
2017-03-15 18:38:18 +00:00
} ,
2017-01-23 17:44:45 +00:00
"ou" : & framework . FieldSchema {
2018-01-17 16:53:49 +00:00
Type : framework . TypeCommaStringSlice ,
2018-02-16 22:19:34 +00:00
Description : ` If set , OU ( OrganizationalUnit ) will be set to
2017-02-16 06:04:29 +00:00
this value in certificates issued by this role . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Organizational Unit" ,
} ,
2017-02-16 06:04:29 +00:00
} ,
"organization" : & framework . FieldSchema {
2018-01-17 16:53:49 +00:00
Type : framework . TypeCommaStringSlice ,
2018-02-16 22:19:34 +00:00
Description : ` If set , O ( Organization ) will be set to
this value in certificates issued by this role . ` ,
} ,
"country" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , Country will be set to
this value in certificates issued by this role . ` ,
} ,
"locality" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , Locality will be set to
this value in certificates issued by this role . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Locality/City" ,
} ,
2018-02-16 22:19:34 +00:00
} ,
"province" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , Province will be set to
this value in certificates issued by this role . ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Province/State" ,
} ,
2018-02-16 22:19:34 +00:00
} ,
"street_address" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , Street Address will be set to
this value in certificates issued by this role . ` ,
} ,
"postal_code" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , Postal Code will be set to
2017-01-23 17:44:45 +00:00
this value in certificates issued by this role . ` ,
} ,
2017-02-24 17:12:40 +00:00
"generate_lease" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2017-02-24 17:12:40 +00:00
Description : `
If set , certificates issued / signed against this role will have Vault leases
attached to them . Defaults to "false" . Certificates can be added to the CRL by
"vault revoke <lease_id>" when certificates are associated with leases . It can
also be done using the "pki/revoke" endpoint . However , when lease generation is
disabled , invoking "pki/revoke" would be the only way to add the certificates
to the CRL . When large number of certificates are generated with long
lifetimes , it is recommended that lease generation be disabled , as large amount of
leases adversely affect the startup time of Vault . ` ,
} ,
2019-02-14 17:42:44 +00:00
2017-04-07 18:25:47 +00:00
"no_store" : & framework . FieldSchema {
2018-03-20 01:01:41 +00:00
Type : framework . TypeBool ,
2017-04-07 18:25:47 +00:00
Description : `
If set , certificates issued / signed against this role will not be stored in the
2017-12-07 15:40:21 +00:00
storage backend . This can improve performance when issuing large numbers of
certificates . However , certificates issued in this way cannot be enumerated
2017-04-07 18:25:47 +00:00
or revoked , so this option is recommended only for certificates that are
non - sensitive , or extremely short - lived . This option implies a value of "false"
for "generate_lease" . ` ,
} ,
2019-02-14 17:42:44 +00:00
2018-02-09 18:42:19 +00:00
"require_cn" : & framework . FieldSchema {
Type : framework . TypeBool ,
Default : true ,
Description : ` If set to false, makes the 'common_name' field optional while generating a certificate. ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Require Common Name" ,
} ,
2018-02-09 18:42:19 +00:00
} ,
2019-02-14 17:42:44 +00:00
2018-03-20 02:05:21 +00:00
"policy_identifiers" : & framework . FieldSchema {
Type : framework . TypeCommaStringSlice ,
Description : ` A comma-separated string or list of policy oids. ` ,
} ,
2019-02-14 17:42:44 +00:00
2018-03-20 02:05:21 +00:00
"basic_constraints_valid_for_non_ca" : & framework . FieldSchema {
Type : framework . TypeBool ,
Description : ` Mark Basic Constraints valid when issuing non-CA certificates. ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Name : "Basic Constraints Valid for Non-CA" ,
} ,
2018-03-20 02:05:21 +00:00
} ,
2018-10-02 15:10:43 +00:00
"not_before_duration" : & framework . FieldSchema {
Type : framework . TypeDurationSecond ,
Default : 30 ,
Description : ` The duration before now the cert needs to be created / signed. ` ,
2019-06-21 15:08:08 +00:00
DisplayAttrs : & framework . DisplayAttributes {
Value : 30 ,
} ,
2018-10-02 15:10:43 +00:00
} ,
2015-05-15 16:13:05 +00:00
} ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
logical . ReadOperation : b . pathRoleRead ,
2016-01-28 20:18:07 +00:00
logical . UpdateOperation : b . pathRoleCreate ,
2015-05-15 16:13:05 +00:00
logical . DeleteOperation : b . pathRoleDelete ,
} ,
HelpSynopsis : pathRoleHelpSyn ,
HelpDescription : pathRoleHelpDesc ,
}
}
2018-01-19 06:44:44 +00:00
func ( b * backend ) getRole ( ctx context . Context , s logical . Storage , n string ) ( * roleEntry , error ) {
entry , err := s . Get ( ctx , "role/" + n )
2015-05-15 16:13:05 +00:00
if err != nil {
return nil , err
}
if entry == nil {
return nil , nil
}
var result roleEntry
if err := entry . DecodeJSON ( & result ) ; err != nil {
return nil , err
}
2015-08-27 19:24:37 +00:00
// Migrate existing saved entries and save back if changed
modified := false
2018-05-09 14:29:54 +00:00
if len ( result . DeprecatedTTL ) == 0 && len ( result . Lease ) != 0 {
result . DeprecatedTTL = result . Lease
2015-08-27 19:24:37 +00:00
result . Lease = ""
modified = true
}
2018-05-09 14:29:54 +00:00
if result . TTL == 0 && len ( result . DeprecatedTTL ) != 0 {
parsed , err := parseutil . ParseDurationSecond ( result . DeprecatedTTL )
if err != nil {
return nil , err
}
result . TTL = parsed
result . DeprecatedTTL = ""
modified = true
}
if len ( result . DeprecatedMaxTTL ) == 0 && len ( result . LeaseMax ) != 0 {
result . DeprecatedMaxTTL = result . LeaseMax
2015-08-27 19:24:37 +00:00
result . LeaseMax = ""
modified = true
}
2018-05-09 14:29:54 +00:00
if result . MaxTTL == 0 && len ( result . DeprecatedMaxTTL ) != 0 {
parsed , err := parseutil . ParseDurationSecond ( result . DeprecatedMaxTTL )
if err != nil {
return nil , err
}
result . MaxTTL = parsed
result . DeprecatedMaxTTL = ""
modified = true
}
2015-12-01 04:49:11 +00:00
if result . AllowBaseDomain {
result . AllowBaseDomain = false
result . AllowBareDomains = true
modified = true
}
2017-12-11 18:13:35 +00:00
if result . AllowedDomainsOld != "" {
result . AllowedDomains = strings . Split ( result . AllowedDomainsOld , "," )
result . AllowedDomainsOld = ""
modified = true
}
2015-12-01 04:49:11 +00:00
if result . AllowedBaseDomain != "" {
found := false
2017-12-11 18:13:35 +00:00
for _ , v := range result . AllowedDomains {
if v == result . AllowedBaseDomain {
found = true
break
2015-12-01 04:49:11 +00:00
}
}
if ! found {
2017-12-11 18:13:35 +00:00
result . AllowedDomains = append ( result . AllowedDomains , result . AllowedBaseDomain )
2015-12-01 04:49:11 +00:00
}
2016-02-09 21:42:15 +00:00
result . AllowedBaseDomain = ""
modified = true
2015-12-01 04:49:11 +00:00
}
2017-02-24 17:12:40 +00:00
// Upgrade generate_lease in role
if result . GenerateLease == nil {
// All the new roles will have GenerateLease always set to a value. A
// nil value indicates that this role needs an upgrade. Set it to
// `true` to not alter its current behavior.
result . GenerateLease = new ( bool )
* result . GenerateLease = true
modified = true
}
2017-12-11 18:13:35 +00:00
// Upgrade key usages
if result . KeyUsageOld != "" {
result . KeyUsage = strings . Split ( result . KeyUsageOld , "," )
result . KeyUsageOld = ""
modified = true
}
2018-01-17 16:53:49 +00:00
// Upgrade OU
if result . OUOld != "" {
result . OU = strings . Split ( result . OUOld , "," )
result . OUOld = ""
modified = true
}
// Upgrade Organization
if result . OrganizationOld != "" {
result . Organization = strings . Split ( result . OrganizationOld , "," )
result . OrganizationOld = ""
modified = true
}
2018-02-03 01:28:25 +00:00
if modified && ( b . System ( ) . LocalMount ( ) || ! b . System ( ) . ReplicationState ( ) . HasState ( consts . ReplicationPerformanceSecondary ) ) {
2015-08-27 19:24:37 +00:00
jsonEntry , err := logical . StorageEntryJSON ( "role/" + n , & result )
if err != nil {
return nil , err
}
2018-01-19 06:44:44 +00:00
if err := s . Put ( ctx , jsonEntry ) ; err != nil {
2017-12-11 18:13:35 +00:00
// Only perform upgrades on replication primary
if ! strings . Contains ( err . Error ( ) , logical . ErrReadOnly . Error ( ) ) {
return nil , err
}
2015-08-27 19:24:37 +00:00
}
}
2015-05-15 16:13:05 +00:00
return & result , nil
}
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleDelete ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2018-01-19 06:44:44 +00:00
err := req . Storage . Delete ( ctx , "role/" + data . Get ( "name" ) . ( string ) )
2015-05-15 16:13:05 +00:00
if err != nil {
return nil , err
}
return nil , nil
}
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleRead ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2017-02-24 17:12:40 +00:00
roleName := data . Get ( "name" ) . ( string )
if roleName == "" {
return logical . ErrorResponse ( "missing role name" ) , nil
}
2018-01-19 06:44:44 +00:00
role , err := b . getRole ( ctx , req . Storage , roleName )
2015-05-15 16:13:05 +00:00
if err != nil {
return nil , err
}
if role == nil {
return nil , nil
}
resp := & logical . Response {
2017-12-11 18:13:35 +00:00
Data : role . ToResponseData ( ) ,
2016-05-26 14:32:04 +00:00
}
2015-05-15 16:13:05 +00:00
return resp , nil
}
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleList ( ctx context . Context , req * logical . Request , d * framework . FieldData ) ( * logical . Response , error ) {
2018-01-19 06:44:44 +00:00
entries , err := req . Storage . List ( ctx , "role/" )
2016-01-28 20:18:07 +00:00
if err != nil {
return nil , err
}
return logical . ListResponse ( entries ) , nil
}
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleCreate ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2015-08-27 19:24:37 +00:00
var err error
2015-05-15 16:13:05 +00:00
name := data . Get ( "name" ) . ( string )
entry := & roleEntry {
2018-05-09 14:29:54 +00:00
MaxTTL : time . Duration ( data . Get ( "max_ttl" ) . ( int ) ) * time . Second ,
TTL : time . Duration ( data . Get ( "ttl" ) . ( int ) ) * time . Second ,
2018-03-20 02:05:21 +00:00
AllowLocalhost : data . Get ( "allow_localhost" ) . ( bool ) ,
AllowedDomains : data . Get ( "allowed_domains" ) . ( [ ] string ) ,
2020-07-08 16:52:25 +00:00
AllowedDomainsTemplate : data . Get ( "allowed_domains_template" ) . ( bool ) ,
2018-03-20 02:05:21 +00:00
AllowBareDomains : data . Get ( "allow_bare_domains" ) . ( bool ) ,
AllowSubdomains : data . Get ( "allow_subdomains" ) . ( bool ) ,
AllowGlobDomains : data . Get ( "allow_glob_domains" ) . ( bool ) ,
AllowAnyName : data . Get ( "allow_any_name" ) . ( bool ) ,
EnforceHostnames : data . Get ( "enforce_hostnames" ) . ( bool ) ,
AllowIPSANs : data . Get ( "allow_ip_sans" ) . ( bool ) ,
2018-06-15 19:32:25 +00:00
AllowedURISANs : data . Get ( "allowed_uri_sans" ) . ( [ ] string ) ,
2018-03-20 02:05:21 +00:00
ServerFlag : data . Get ( "server_flag" ) . ( bool ) ,
ClientFlag : data . Get ( "client_flag" ) . ( bool ) ,
CodeSigningFlag : data . Get ( "code_signing_flag" ) . ( bool ) ,
EmailProtectionFlag : data . Get ( "email_protection_flag" ) . ( bool ) ,
KeyType : data . Get ( "key_type" ) . ( string ) ,
KeyBits : data . Get ( "key_bits" ) . ( int ) ,
UseCSRCommonName : data . Get ( "use_csr_common_name" ) . ( bool ) ,
UseCSRSANs : data . Get ( "use_csr_sans" ) . ( bool ) ,
KeyUsage : data . Get ( "key_usage" ) . ( [ ] string ) ,
2018-06-15 22:20:43 +00:00
ExtKeyUsage : data . Get ( "ext_key_usage" ) . ( [ ] string ) ,
2018-06-01 13:13:54 +00:00
ExtKeyUsageOIDs : data . Get ( "ext_key_usage_oids" ) . ( [ ] string ) ,
2018-03-20 02:05:21 +00:00
OU : data . Get ( "ou" ) . ( [ ] string ) ,
Organization : data . Get ( "organization" ) . ( [ ] string ) ,
Country : data . Get ( "country" ) . ( [ ] string ) ,
Locality : data . Get ( "locality" ) . ( [ ] string ) ,
Province : data . Get ( "province" ) . ( [ ] string ) ,
StreetAddress : data . Get ( "street_address" ) . ( [ ] string ) ,
PostalCode : data . Get ( "postal_code" ) . ( [ ] string ) ,
GenerateLease : new ( bool ) ,
NoStore : data . Get ( "no_store" ) . ( bool ) ,
RequireCN : data . Get ( "require_cn" ) . ( bool ) ,
2018-06-05 03:18:39 +00:00
AllowedSerialNumbers : data . Get ( "allowed_serial_numbers" ) . ( [ ] string ) ,
2018-03-20 02:05:21 +00:00
PolicyIdentifiers : data . Get ( "policy_identifiers" ) . ( [ ] string ) ,
BasicConstraintsValidForNonCA : data . Get ( "basic_constraints_valid_for_non_ca" ) . ( bool ) ,
2018-10-02 15:10:43 +00:00
NotBeforeDuration : time . Duration ( data . Get ( "not_before_duration" ) . ( int ) ) * time . Second ,
2015-05-15 16:13:05 +00:00
}
2019-12-11 15:16:44 +00:00
allowedOtherSANs := data . Get ( "allowed_other_sans" ) . ( [ ] string )
switch {
case len ( allowedOtherSANs ) == 0 :
case len ( allowedOtherSANs ) == 1 && allowedOtherSANs [ 0 ] == "*" :
default :
_ , err := parseOtherSANs ( allowedOtherSANs )
2018-02-16 22:19:34 +00:00
if err != nil {
return logical . ErrorResponse ( errwrap . Wrapf ( "error parsing allowed_other_sans: {{err}}" , err ) . Error ( ) ) , nil
}
}
2019-12-11 15:16:44 +00:00
entry . AllowedOtherSANs = allowedOtherSANs
2018-02-16 22:19:34 +00:00
2017-04-07 18:25:47 +00:00
// no_store implies generate_lease := false
if entry . NoStore {
* entry . GenerateLease = false
} else {
* entry . GenerateLease = data . Get ( "generate_lease" ) . ( bool )
}
2017-02-24 17:12:40 +00:00
2016-02-18 22:55:47 +00:00
if entry . KeyType == "rsa" && entry . KeyBits < 2048 {
return logical . ErrorResponse ( "RSA keys < 2048 bits are unsafe and not supported" ) , nil
}
2018-05-09 14:29:54 +00:00
if entry . MaxTTL > 0 && entry . TTL > entry . MaxTTL {
2018-03-20 01:01:41 +00:00
return logical . ErrorResponse (
` "ttl" value must be less than "max_ttl" value ` ,
) , nil
2015-05-15 16:13:05 +00:00
}
2019-05-09 15:43:11 +00:00
if err := certutil . ValidateKeyTypeLength ( entry . KeyType , entry . KeyBits ) ; err != nil {
return logical . ErrorResponse ( err . Error ( ) ) , nil
2015-05-15 16:13:05 +00:00
}
2018-06-01 13:13:54 +00:00
if len ( entry . ExtKeyUsageOIDs ) > 0 {
for _ , oidstr := range entry . ExtKeyUsageOIDs {
2019-05-09 15:43:11 +00:00
_ , err := certutil . StringToOid ( oidstr )
2018-06-01 13:13:54 +00:00
if err != nil {
return logical . ErrorResponse ( fmt . Sprintf ( "%q could not be parsed as a valid oid for an extended key usage" , oidstr ) ) , nil
}
}
}
2018-03-20 02:10:18 +00:00
if len ( entry . PolicyIdentifiers ) > 0 {
for _ , oidstr := range entry . PolicyIdentifiers {
2019-05-09 15:43:11 +00:00
_ , err := certutil . StringToOid ( oidstr )
2018-03-20 02:10:18 +00:00
if err != nil {
return logical . ErrorResponse ( fmt . Sprintf ( "%q could not be parsed as a valid oid for a policy identifier" , oidstr ) ) , nil
}
}
}
2015-05-15 16:13:05 +00:00
// Store it
jsonEntry , err := logical . StorageEntryJSON ( "role/" + name , entry )
if err != nil {
return nil , err
}
2018-01-19 06:44:44 +00:00
if err := req . Storage . Put ( ctx , jsonEntry ) ; err != nil {
2015-05-15 16:13:05 +00:00
return nil , err
}
return nil , nil
}
2017-12-11 18:13:35 +00:00
func parseKeyUsages ( input [ ] string ) int {
2016-06-22 20:08:24 +00:00
var parsedKeyUsages x509 . KeyUsage
2017-12-11 18:13:35 +00:00
for _ , k := range input {
2016-06-23 14:18:03 +00:00
switch strings . ToLower ( strings . TrimSpace ( k ) ) {
2016-06-22 20:08:24 +00:00
case "digitalsignature" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageDigitalSignature
2016-06-22 20:08:24 +00:00
case "contentcommitment" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageContentCommitment
2016-06-22 20:08:24 +00:00
case "keyencipherment" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageKeyEncipherment
2016-06-22 20:08:24 +00:00
case "dataencipherment" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageDataEncipherment
2016-06-22 20:08:24 +00:00
case "keyagreement" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageKeyAgreement
2016-06-22 20:08:24 +00:00
case "certsign" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageCertSign
2016-06-22 20:08:24 +00:00
case "crlsign" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageCRLSign
2016-06-22 20:08:24 +00:00
case "encipheronly" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageEncipherOnly
2016-06-22 20:08:24 +00:00
case "decipheronly" :
2016-06-23 14:18:03 +00:00
parsedKeyUsages |= x509 . KeyUsageDecipherOnly
2016-06-22 20:08:24 +00:00
}
}
return int ( parsedKeyUsages )
}
2019-05-09 15:43:11 +00:00
func parseExtKeyUsages ( role * roleEntry ) certutil . CertExtKeyUsage {
var parsedKeyUsages certutil . CertExtKeyUsage
2018-06-15 22:20:43 +00:00
if role . ServerFlag {
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . ServerAuthExtKeyUsage
2018-06-15 22:20:43 +00:00
}
if role . ClientFlag {
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . ClientAuthExtKeyUsage
2018-06-15 22:20:43 +00:00
}
if role . CodeSigningFlag {
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . CodeSigningExtKeyUsage
2018-06-15 22:20:43 +00:00
}
if role . EmailProtectionFlag {
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . EmailProtectionExtKeyUsage
2018-06-15 22:20:43 +00:00
}
for _ , k := range role . ExtKeyUsage {
switch strings . ToLower ( strings . TrimSpace ( k ) ) {
case "any" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . AnyExtKeyUsage
2018-06-15 22:20:43 +00:00
case "serverauth" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . ServerAuthExtKeyUsage
2018-06-15 22:20:43 +00:00
case "clientauth" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . ClientAuthExtKeyUsage
2018-06-15 22:20:43 +00:00
case "codesigning" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . CodeSigningExtKeyUsage
2018-06-15 22:20:43 +00:00
case "emailprotection" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . EmailProtectionExtKeyUsage
2018-06-15 22:20:43 +00:00
case "ipsecendsystem" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . IpsecEndSystemExtKeyUsage
2018-06-15 22:20:43 +00:00
case "ipsectunnel" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . IpsecTunnelExtKeyUsage
2018-06-15 22:20:43 +00:00
case "ipsecuser" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . IpsecUserExtKeyUsage
2018-06-15 22:20:43 +00:00
case "timestamping" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . TimeStampingExtKeyUsage
2018-06-15 22:20:43 +00:00
case "ocspsigning" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . OcspSigningExtKeyUsage
2018-06-15 22:20:43 +00:00
case "microsoftservergatedcrypto" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . MicrosoftServerGatedCryptoExtKeyUsage
2018-06-15 22:20:43 +00:00
case "netscapeservergatedcrypto" :
2019-05-09 15:43:11 +00:00
parsedKeyUsages |= certutil . NetscapeServerGatedCryptoExtKeyUsage
2018-06-15 22:20:43 +00:00
}
}
return parsedKeyUsages
}
2015-05-15 16:13:05 +00:00
type roleEntry struct {
2018-05-09 14:29:54 +00:00
LeaseMax string ` json:"lease_max" `
Lease string ` json:"lease" `
DeprecatedMaxTTL string ` json:"max_ttl" mapstructure:"max_ttl" `
DeprecatedTTL string ` json:"ttl" mapstructure:"ttl" `
TTL time . Duration ` json:"ttl_duration" mapstructure:"ttl_duration" `
MaxTTL time . Duration ` json:"max_ttl_duration" mapstructure:"max_ttl_duration" `
AllowLocalhost bool ` json:"allow_localhost" mapstructure:"allow_localhost" `
AllowedBaseDomain string ` json:"allowed_base_domain" mapstructure:"allowed_base_domain" `
2020-03-07 02:41:26 +00:00
AllowedDomainsOld string ` json:"allowed_domains,omitempty" `
2018-05-09 14:29:54 +00:00
AllowedDomains [ ] string ` json:"allowed_domains_list" mapstructure:"allowed_domains" `
2020-07-08 16:52:25 +00:00
AllowedDomainsTemplate bool ` json:"allowed_domains_template" `
2018-05-09 14:29:54 +00:00
AllowBaseDomain bool ` json:"allow_base_domain" `
AllowBareDomains bool ` json:"allow_bare_domains" mapstructure:"allow_bare_domains" `
AllowTokenDisplayName bool ` json:"allow_token_displayname" mapstructure:"allow_token_displayname" `
AllowSubdomains bool ` json:"allow_subdomains" mapstructure:"allow_subdomains" `
AllowGlobDomains bool ` json:"allow_glob_domains" mapstructure:"allow_glob_domains" `
AllowAnyName bool ` json:"allow_any_name" mapstructure:"allow_any_name" `
EnforceHostnames bool ` json:"enforce_hostnames" mapstructure:"enforce_hostnames" `
AllowIPSANs bool ` json:"allow_ip_sans" mapstructure:"allow_ip_sans" `
ServerFlag bool ` json:"server_flag" mapstructure:"server_flag" `
ClientFlag bool ` json:"client_flag" mapstructure:"client_flag" `
CodeSigningFlag bool ` json:"code_signing_flag" mapstructure:"code_signing_flag" `
EmailProtectionFlag bool ` json:"email_protection_flag" mapstructure:"email_protection_flag" `
UseCSRCommonName bool ` json:"use_csr_common_name" mapstructure:"use_csr_common_name" `
UseCSRSANs bool ` json:"use_csr_sans" mapstructure:"use_csr_sans" `
KeyType string ` json:"key_type" mapstructure:"key_type" `
KeyBits int ` json:"key_bits" mapstructure:"key_bits" `
MaxPathLength * int ` json:",omitempty" mapstructure:"max_path_length" `
KeyUsageOld string ` json:"key_usage,omitempty" `
KeyUsage [ ] string ` json:"key_usage_list" mapstructure:"key_usage" `
2018-06-15 22:20:43 +00:00
ExtKeyUsage [ ] string ` json:"extended_key_usage_list" mapstructure:"extended_key_usage" `
2018-05-09 14:29:54 +00:00
OUOld string ` json:"ou,omitempty" `
OU [ ] string ` json:"ou_list" mapstructure:"ou" `
OrganizationOld string ` json:"organization,omitempty" `
Organization [ ] string ` json:"organization_list" mapstructure:"organization" `
Country [ ] string ` json:"country" mapstructure:"country" `
Locality [ ] string ` json:"locality" mapstructure:"locality" `
Province [ ] string ` json:"province" mapstructure:"province" `
StreetAddress [ ] string ` json:"street_address" mapstructure:"street_address" `
PostalCode [ ] string ` json:"postal_code" mapstructure:"postal_code" `
GenerateLease * bool ` json:"generate_lease,omitempty" `
NoStore bool ` json:"no_store" mapstructure:"no_store" `
RequireCN bool ` json:"require_cn" mapstructure:"require_cn" `
AllowedOtherSANs [ ] string ` json:"allowed_other_sans" mapstructure:"allowed_other_sans" `
2018-06-05 03:18:39 +00:00
AllowedSerialNumbers [ ] string ` json:"allowed_serial_numbers" mapstructure:"allowed_serial_numbers" `
2018-06-15 19:32:25 +00:00
AllowedURISANs [ ] string ` json:"allowed_uri_sans" mapstructure:"allowed_uri_sans" `
2018-05-09 14:29:54 +00:00
PolicyIdentifiers [ ] string ` json:"policy_identifiers" mapstructure:"policy_identifiers" `
2018-06-01 13:13:54 +00:00
ExtKeyUsageOIDs [ ] string ` json:"ext_key_usage_oids" mapstructure:"ext_key_usage_oids" `
2018-05-09 14:29:54 +00:00
BasicConstraintsValidForNonCA bool ` json:"basic_constraints_valid_for_non_ca" mapstructure:"basic_constraints_valid_for_non_ca" `
2018-10-02 15:10:43 +00:00
NotBeforeDuration time . Duration ` json:"not_before_duration" mapstructure:"not_before_duration" `
2017-09-13 15:42:45 +00:00
// Used internally for signing intermediates
AllowExpirationPastCA bool
2015-05-15 16:13:05 +00:00
}
2017-12-11 18:13:35 +00:00
func ( r * roleEntry ) ToResponseData ( ) map [ string ] interface { } {
responseData := map [ string ] interface { } {
2018-05-09 14:29:54 +00:00
"ttl" : int64 ( r . TTL . Seconds ( ) ) ,
"max_ttl" : int64 ( r . MaxTTL . Seconds ( ) ) ,
2018-03-20 02:05:21 +00:00
"allow_localhost" : r . AllowLocalhost ,
"allowed_domains" : r . AllowedDomains ,
2020-07-08 16:52:25 +00:00
"allowed_domains_template" : r . AllowedDomainsTemplate ,
2018-03-20 02:05:21 +00:00
"allow_bare_domains" : r . AllowBareDomains ,
"allow_token_displayname" : r . AllowTokenDisplayName ,
"allow_subdomains" : r . AllowSubdomains ,
"allow_glob_domains" : r . AllowGlobDomains ,
"allow_any_name" : r . AllowAnyName ,
"enforce_hostnames" : r . EnforceHostnames ,
"allow_ip_sans" : r . AllowIPSANs ,
"server_flag" : r . ServerFlag ,
"client_flag" : r . ClientFlag ,
"code_signing_flag" : r . CodeSigningFlag ,
"email_protection_flag" : r . EmailProtectionFlag ,
"use_csr_common_name" : r . UseCSRCommonName ,
"use_csr_sans" : r . UseCSRSANs ,
"key_type" : r . KeyType ,
"key_bits" : r . KeyBits ,
"key_usage" : r . KeyUsage ,
2018-06-15 22:20:43 +00:00
"ext_key_usage" : r . ExtKeyUsage ,
2018-06-01 13:13:54 +00:00
"ext_key_usage_oids" : r . ExtKeyUsageOIDs ,
2018-03-20 02:05:21 +00:00
"ou" : r . OU ,
"organization" : r . Organization ,
"country" : r . Country ,
"locality" : r . Locality ,
"province" : r . Province ,
"street_address" : r . StreetAddress ,
"postal_code" : r . PostalCode ,
"no_store" : r . NoStore ,
"allowed_other_sans" : r . AllowedOtherSANs ,
2018-06-05 03:18:39 +00:00
"allowed_serial_numbers" : r . AllowedSerialNumbers ,
2018-06-15 19:32:25 +00:00
"allowed_uri_sans" : r . AllowedURISANs ,
2018-04-09 02:09:29 +00:00
"require_cn" : r . RequireCN ,
2018-03-20 02:05:21 +00:00
"policy_identifiers" : r . PolicyIdentifiers ,
"basic_constraints_valid_for_non_ca" : r . BasicConstraintsValidForNonCA ,
2018-10-02 15:10:43 +00:00
"not_before_duration" : int64 ( r . NotBeforeDuration . Seconds ( ) ) ,
2017-12-11 18:13:35 +00:00
}
if r . MaxPathLength != nil {
responseData [ "max_path_length" ] = r . MaxPathLength
}
if r . GenerateLease != nil {
responseData [ "generate_lease" ] = r . GenerateLease
}
return responseData
}
2016-06-20 23:51:04 +00:00
const pathListRolesHelpSyn = ` List the existing roles in this backend `
const pathListRolesHelpDesc = ` Roles will be listed by the role name. `
const pathRoleHelpSyn = ` Manage the roles that can be created with this backend. `
2015-05-15 16:13:05 +00:00
2016-06-20 23:51:04 +00:00
const pathRoleHelpDesc = ` This path lets you manage the roles that can be created with this backend. `