func (pki *PKI) Revoke(serial string) error {
	path := fmt.Sprintf("%s/revoke", pki.path)
	contents := map[string]interface{}{
		"serial_number": serial,
	}
	if _, err := pki.client.Logical().Write(path, contents); err != nil {
		return fmt.Errorf("failed to revoke certificate: %s", err)
	}
	return nil
}
Revoke revokes the certificate with the given serial.
package crypto
import (
	"crypto/x509"
	"encoding/json"
	"fmt"
	"time"
	vaultapi "github.com/hashicorp/vault/api"
)
type PKI struct {
	client *vaultapi.Client
	path   string
}
type PKICertificate struct {
	Serial        string
	Certificate   string
	PrivateKey    string
	CACertificate string
	Expiration    time.Time
}
type PKICrl struct {
	Certificate string
}
type PKIConfig struct {
	CommonName         string
	Validity           time.Duration
	RSABits            int
	Organization       string
	OrganizationalUnit string
	Country            string
	Locality           string
}
type PKIRoleConfig struct {
	DefaultValidity time.Duration
	RSABits         int
	Server          bool
}
func NewPKI(vault *vaultapi.Client, path string) *PKI {
	return &PKI{client: vault, path: path}
}
func (pki *PKI) EnsureEnabled() error {
	mounts, err := pki.client.Sys().ListMounts()
	if err != nil {
		return fmt.Errorf("failed to list existing mount paths: %s", err)
	}
	if _, ok := mounts[pki.path+"/"]; ok {
		return nil
	}
	input := &vaultapi.MountInput{
		Type: "pki",
		Config: vaultapi.MountConfigInput{
			DefaultLeaseTTL: "2592000",    
			MaxLeaseTTL:     "315360000",  
		},
	}
	if err := pki.client.Sys().Mount(pki.path, input); err != nil {
		return fmt.Errorf("failed to create mount for PKI: %s", err)
	}
	path := fmt.Sprintf("%s/config/crl", pki.path)
	content := map[string]interface{}{
		"expiry":  "72h",
		"disable": false,
	}
	if _, err := pki.client.Logical().Write(path, content); err != nil {
		return fmt.Errorf("failed to set CRL configuration: %s", err)
	}
	return nil
}
func (pki *PKI) DisableIfEnabled() error {
	if err := pki.client.Sys().Unmount(pki.path); err != nil {
		return fmt.Errorf("failed to disable PKI: %s", err)
	}
	return nil
}
func (pki *PKI) GenerateRootIfRequired(config PKIConfig) error {
	path := fmt.Sprintf("%s/root/generate/internal", pki.path)
	contents := map[string]interface{}{
		"common_name":          config.CommonName,
		"key_type":             "rsa",
		"key_bits":             config.RSABits,
		"ttl":                  fmt.Sprintf("%ds", int(config.Validity.Seconds())),
		"exclude_cn_from_sans": true,
	}
	if config.Organization != "" {
		contents["organization"] = config.Organization
	}
	if config.OrganizationalUnit != "" {
		contents["ou"] = config.OrganizationalUnit
	}
	if config.Country != "" {
		contents["country"] = config.Country
	}
	if config.Locality != "" {
		contents["locality"] = config.Locality
	}
	if _, err := pki.client.Logical().Write(path, contents); err != nil {
		return fmt.Errorf("failed to verify and possibly create root key: %s", err)
	}
	return nil
}
func (pki *PKI) ConfigureRole(name string, config PKIRoleConfig) error {
	var extensions []string
	if config.Server {
		extensions = []string{"TLS Web Server Authentication"}
	} else {
		extensions = []string{"TLS Web Client Authentication"}
	}
	path := fmt.Sprintf("%s/roles/%s", pki.path, name)
	contents := map[string]interface{}{
		"key_type":            "rsa",
		"key_bits":            config.RSABits,
		"ttl":                 fmt.Sprintf("%ds", int(config.DefaultValidity.Seconds())),
		"max_ttl":             "87600h",
		"allow_any_name":      true,
		"server_flag":         config.Server,
		"client_flag":         !config.Server,
		"generate_lease":      false,
		"not_before_duration": "15m",
		"key_usage":           []string{"DigitalSignature", "KeyAgreement", "KeyEncipherment"},
		"ext_key_usage":       extensions,
	}
	if _, err := pki.client.Logical().Write(path, contents); err != nil {
		return fmt.Errorf("failed to update role configuration: %s", err)
	}
	return nil
}
func (pki *PKI) Generate(role, commonName string, validity time.Duration) (PKICertificate, error) {
	path := fmt.Sprintf("%s/issue/%s", pki.path, role)
	contents := map[string]interface{}{
		"common_name": commonName,
		"format":      "pem",
	}
	if validity > 0 {
		contents["ttl"] = fmt.Sprintf("%ds", int(validity.Seconds()))
	}
	result, err := pki.client.Logical().Write(path, contents)
	if err != nil {
		return PKICertificate{}, fmt.Errorf("failed to generate certificate: %s", err)
	}
	expiration, err := result.Data["expiration"].(json.Number).Int64()
	if err != nil {
		return PKICertificate{}, fmt.Errorf("invalid expiration date: %s", err)
	}
	return PKICertificate{
		Serial:        result.Data["serial_number"].(string),
		Certificate:   result.Data["certificate"].(string),
		PrivateKey:    result.Data["private_key"].(string),
		CACertificate: result.Data["issuing_ca"].(string),
		Expiration:    time.Unix(expiration, 0),
	}, nil
}