2015-10-14 01:13:40 +00:00
|
|
|
package pki
|
|
|
|
|
|
|
|
import (
|
2018-01-08 18:31:38 +00:00
|
|
|
"context"
|
2015-10-14 01:13:40 +00:00
|
|
|
"fmt"
|
|
|
|
|
2015-11-19 16:32:18 +00:00
|
|
|
"github.com/asaskevich/govalidator"
|
2015-10-14 01:13:40 +00:00
|
|
|
"github.com/fatih/structs"
|
2019-04-12 21:54:35 +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-13 07:44:06 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
2015-10-14 01:13:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func pathConfigURLs(b *backend) *framework.Path {
|
|
|
|
return &framework.Path{
|
2015-10-14 18:48:51 +00:00
|
|
|
Pattern: "config/urls",
|
2015-10-14 01:13:40 +00:00
|
|
|
Fields: map[string]*framework.FieldSchema{
|
2015-10-14 18:48:51 +00:00
|
|
|
"issuing_certificates": &framework.FieldSchema{
|
2017-10-03 20:13:57 +00:00
|
|
|
Type: framework.TypeCommaStringSlice,
|
2015-10-14 18:48:51 +00:00
|
|
|
Description: `Comma-separated list of URLs to be used
|
|
|
|
for the issuing certificate attribute`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"crl_distribution_points": &framework.FieldSchema{
|
2017-10-03 20:13:57 +00:00
|
|
|
Type: framework.TypeCommaStringSlice,
|
2015-10-14 18:48:51 +00:00
|
|
|
Description: `Comma-separated list of URLs to be used
|
|
|
|
for the CRL distribution points attribute`,
|
2015-10-14 01:13:40 +00:00
|
|
|
},
|
2015-10-14 18:48:51 +00:00
|
|
|
|
|
|
|
"ocsp_servers": &framework.FieldSchema{
|
2017-10-03 20:13:57 +00:00
|
|
|
Type: framework.TypeCommaStringSlice,
|
2015-10-14 01:13:40 +00:00
|
|
|
Description: `Comma-separated list of URLs to be used
|
2015-10-14 18:48:51 +00:00
|
|
|
for the OCSP servers attribute`,
|
2015-10-14 01:13:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.pathWriteURL,
|
2016-07-19 17:54:18 +00:00
|
|
|
logical.ReadOperation: b.pathReadURL,
|
2015-10-14 01:13:40 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: pathConfigURLsHelpSyn,
|
|
|
|
HelpDescription: pathConfigURLsHelpDesc,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-19 16:32:18 +00:00
|
|
|
func validateURLs(urls []string) string {
|
2015-11-16 19:19:10 +00:00
|
|
|
for _, curr := range urls {
|
2015-11-19 16:32:18 +00:00
|
|
|
if !govalidator.IsURL(curr) {
|
|
|
|
return curr
|
2015-11-16 19:19:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-19 16:32:18 +00:00
|
|
|
return ""
|
2015-11-16 19:19:10 +00:00
|
|
|
}
|
|
|
|
|
2019-05-09 15:43:11 +00:00
|
|
|
func getURLs(ctx context.Context, req *logical.Request) (*certutil.URLEntries, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
entry, err := req.Storage.Get(ctx, "urls")
|
2015-10-14 01:13:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if entry == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2019-05-09 15:43:11 +00:00
|
|
|
var entries certutil.URLEntries
|
2015-10-14 01:13:40 +00:00
|
|
|
if err := entry.DecodeJSON(&entries); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &entries, nil
|
|
|
|
}
|
|
|
|
|
2019-05-09 15:43:11 +00:00
|
|
|
func writeURLs(ctx context.Context, req *logical.Request, entries *certutil.URLEntries) error {
|
2015-10-14 19:53:57 +00:00
|
|
|
entry, err := logical.StorageEntryJSON("urls", entries)
|
2015-10-14 01:13:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if entry == nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return fmt.Errorf("unable to marshal entry into JSON")
|
2015-10-14 01:13:40 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
err = req.Storage.Put(ctx, entry)
|
2015-10-14 01:13:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *backend) pathReadURL(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
entries, err := getURLs(ctx, req)
|
2015-10-14 01:13:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if entries == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: structs.New(entries).Map(),
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *backend) pathWriteURL(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
entries, err := getURLs(ctx, req)
|
2015-10-14 01:13:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if entries == nil {
|
2019-05-09 15:43:11 +00:00
|
|
|
entries = &certutil.URLEntries{
|
2015-10-14 18:48:51 +00:00
|
|
|
IssuingCertificates: []string{},
|
|
|
|
CRLDistributionPoints: []string{},
|
|
|
|
OCSPServers: []string{},
|
2015-10-14 01:13:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-14 18:48:51 +00:00
|
|
|
if urlsInt, ok := data.GetOk("issuing_certificates"); ok {
|
2017-10-03 20:13:57 +00:00
|
|
|
entries.IssuingCertificates = urlsInt.([]string)
|
2016-07-19 17:54:18 +00:00
|
|
|
if badURL := validateURLs(entries.IssuingCertificates); badURL != "" {
|
2015-11-16 19:19:10 +00:00
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
2016-07-19 17:54:18 +00:00
|
|
|
"invalid URL found in issuing certificates: %s", badURL)), nil
|
2015-11-16 19:19:10 +00:00
|
|
|
}
|
2015-10-14 18:48:51 +00:00
|
|
|
}
|
|
|
|
if urlsInt, ok := data.GetOk("crl_distribution_points"); ok {
|
2017-10-03 20:13:57 +00:00
|
|
|
entries.CRLDistributionPoints = urlsInt.([]string)
|
2016-07-19 17:54:18 +00:00
|
|
|
if badURL := validateURLs(entries.CRLDistributionPoints); badURL != "" {
|
2015-11-16 19:19:10 +00:00
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
2016-07-19 17:54:18 +00:00
|
|
|
"invalid URL found in CRL distribution points: %s", badURL)), nil
|
2015-11-16 19:19:10 +00:00
|
|
|
}
|
2015-10-14 18:48:51 +00:00
|
|
|
}
|
|
|
|
if urlsInt, ok := data.GetOk("ocsp_servers"); ok {
|
2017-10-03 20:13:57 +00:00
|
|
|
entries.OCSPServers = urlsInt.([]string)
|
2016-07-19 17:54:18 +00:00
|
|
|
if badURL := validateURLs(entries.OCSPServers); badURL != "" {
|
2015-11-16 19:19:10 +00:00
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
2016-07-19 17:54:18 +00:00
|
|
|
"invalid URL found in OCSP servers: %s", badURL)), nil
|
2015-11-16 19:19:10 +00:00
|
|
|
}
|
2015-10-14 01:13:40 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
return nil, writeURLs(ctx, req, entries)
|
2015-10-14 01:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const pathConfigURLsHelpSyn = `
|
|
|
|
Set the URLs for the issuing CA, CRL distribution points, and OCSP servers.
|
|
|
|
`
|
|
|
|
|
|
|
|
const pathConfigURLsHelpDesc = `
|
|
|
|
This path allows you to set the issuing CA, CRL distribution points, and
|
|
|
|
OCSP server URLs that will be encoded into issued certificates. If these
|
2015-10-14 19:53:57 +00:00
|
|
|
values are not set, no such information will be encoded in the issued
|
|
|
|
certificates. To delete URLs, simply re-set the appropriate value with an
|
|
|
|
empty string.
|
2015-10-14 01:13:40 +00:00
|
|
|
|
|
|
|
Multiple URLs can be specified for each type; use commas to separate them.
|
|
|
|
`
|