func (c *CloudKitKeyManager) SecretsFolder() string {
	file, err := os.Open(c.secretsFolder)
	defer file.Close()
	if err != nil {
		path, createErr := createSecretsFolder(c.secretsFolder)
		if createErr != nil {
			log.Debugf("%s", createErr)
		}
		return path
	}
	return file.Name()
}
SecretsFolder returns the path to Sputnik's secrets folder
package keymanager
import (
	"crypto/ecdsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"strings"
	log "github.com/apex/log"
)
const KeyIDEnvironmentVariableName = string("SPUTNIK_CLOUDKIT_KEYID")
type KeyManager interface {
	PublicKey() *ecdsa.PublicKey
	PrivateKey() *ecdsa.PrivateKey
	KeyID() string
	RemoveSigningIdentity() error
	StoreKeyID(key string) error
}
type CloudKitKeyManager struct {
	secretsFolder      string
	pemFileName        string
	keyIDFileName      string
	inMemoryKeyID      string
	inMemoryPrivateKey *ecdsa.PrivateKey
	inMemoryPublicKey  *ecdsa.PublicKey
}
func New() CloudKitKeyManager {
	homeDir := homeDir()
	components := []string{homeDir, ".sputnik", "secrets"}
	secretsFolder := strings.Join(components, "/")
	keyIDFileName := "keyid.txt"
	pemFileName := "eckey.pem"
	return NewWithSecretsFolder(secretsFolder, keyIDFileName, pemFileName)
}
func NewWithSecretsFolder(secretsFolder string, keyIDFileName string, pemFileName string) CloudKitKeyManager {
	return CloudKitKeyManager{
		secretsFolder: secretsFolder,
		pemFileName:   pemFileName,
		keyIDFileName: keyIDFileName}
}
func (c *CloudKitKeyManager) KeyID() string {
	keyID := os.Getenv("SPUTNIK_CLOUDKIT_KEYID")
	if len(keyID) <= 0 {
		keyIDFromFile, err := c.storedKeyID()
		if err != nil {
		}
		return keyIDFromFile
	}
	return keyID
}
func (c *CloudKitKeyManager) StoreKeyID(key string) error {
	path := c.keyIDFilePath()
	keyBytes := []byte(key)
	return ioutil.WriteFile(path, keyBytes, 0644)
}
func (c *CloudKitKeyManager) storedKeyID() (string, error) {
	if len(c.inMemoryKeyID) > 0 {
		return c.inMemoryKeyID, nil
	}
	path := c.keyIDFilePath()
	keyBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}
	c.inMemoryKeyID = string(keyBytes)
	return c.inMemoryKeyID, nil
}
func (c *CloudKitKeyManager) PrivateKey() *ecdsa.PrivateKey {
	if c.inMemoryPrivateKey != nil {
		return c.inMemoryPrivateKey
	}
	inPathPem := c.pemFilePath()
	command := exec.Command("openssl", "ec", "-outform", "der", "-in", inPathPem)
	bytes, _ := command.Output()
	privateKey, err := x509.ParseECPrivateKey(bytes)
	if err != nil {
		log.Error("Failed to parse private ec key from pem:")
		log.Errorf("%s", err)
		return nil
	}
	c.inMemoryPrivateKey = privateKey
	return c.inMemoryPrivateKey
}
func (c *CloudKitKeyManager) PublicKey() *ecdsa.PublicKey {
	if c.inMemoryPublicKey != nil {
		return c.inMemoryPublicKey
	}
	var err error
	var pub interface{}
	pemString := c.PublicKeyString()
	pemData := []byte(pemString)
	block, _ := pem.Decode(pemData)
	if block == nil || block.Type != "PUBLIC KEY" {
		err = errors.New("failed to decode PEM block containing public key")
	} else {
		pub, err = x509.ParsePKIXPublicKey(block.Bytes)
		switch pub := pub.(type) {
		case *ecdsa.PublicKey:
			c.inMemoryPublicKey = pub
			return pub
		}
	}
	if err != nil {
		log.Error("unable to parse public key from certificate:")
		log.Errorf("%s", err)
	}
	return nil
}
func (c *CloudKitKeyManager) PublicKeyString() string {
	ecKeyPath := c.pemFilePath()
	command := exec.Command("openssl", "ec", "-in", ecKeyPath, "-pubout")
	bytes, err := command.Output()
	if err != nil {
		log.Error("PublicKeyString")
		log.Error("Failed to read the public key from PEM")
		log.Errorf("%s", err)
	}
	return string(bytes)
}
func (c *CloudKitKeyManager) SigningIdentityExists() (bool, error) {
	ecKeyPath := c.pemFilePath()
	file, openError := os.Open(ecKeyPath)
	defer file.Close()
	return file != nil && openError == nil, openError
}
func (c *CloudKitKeyManager) keyIDFilePath() string {
	secretsFolder := c.SecretsFolder()
	return secretsFolder + "/" + c.keyIDFileName
}
func (c *CloudKitKeyManager) pemFilePath() string {
	secretsFolder := c.SecretsFolder()
	return secretsFolder + "/" + c.pemFileName
}
func (c *CloudKitKeyManager) ECKey() string {
	ecKeyPath := c.pemFilePath()
	command := exec.Command("openssl", "ec", "-in", ecKeyPath, "-pubout")
	bytes, err := command.Output()
	if err != nil {
		log.Error("ECKey")
		log.Error("Failed to read the public key from PEM")
		log.Errorf("%s", err)
	}
	return string(bytes)
}
func (c *CloudKitKeyManager) CreateSigningIdentity() error {
	return c.createPemEncodedCertificate()
}
func (c *CloudKitKeyManager) RemoveSigningIdentity() error {
	c.inMemoryPrivateKey = nil
	c.inMemoryPublicKey = nil
	removePemCommand := exec.Command("rm", c.pemFilePath())
	err := removePemCommand.Run()
	if err != nil {
		log.Error("Unable to remove PEM:")
		log.Errorf("%s", err)
	}
	removeKeyIDCommand := exec.Command("rm", c.keyIDFilePath())
	err = removeKeyIDCommand.Run()
	return err
}
func (c *CloudKitKeyManager) createPemEncodedCertificate() error {
	log.Debug("Creating PEM...")
	pemFilePath := c.pemFilePath()
	command := exec.Command("openssl", "ecparam", "-name", "prime256v1", "-genkey", "-noout", "-out", pemFilePath)
	err := command.Start()
	if err != nil {
		log.Error("Failed to create pem encoded certificate")
		log.Errorf("%s", err)
	}
	err = command.Wait()
	if err != nil {
		log.Error("Error executing `openssl`")
		log.Errorf("%s", err)
	}
	log.Info("Done creating PEM")
	return err
}