app/registry/key.go (145 lines of code) (raw):
package registry
import (
"encoding/base64"
"fmt"
"io/ioutil"
"mime/multipart"
"net/http"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
const (
KeyManagementVaultPath = "key-management"
)
type KeyManagement interface {
KeyDeviceType() string
AllowedKeysIssuer() []string
AllowedKeysSerial() []string
SignKeyIssuer() string
SignKeyPwd() string
RemoteType() string
RemoteSerialNumber() string
RemoteKeyPort() string
RemoteKeyHost() string
RemoteKeyPassword() string
INIConfig() string
VaultSecretPath() string
KeyDataChanged() bool
KeyVerificationChanged() bool
}
type DigitalSignature struct {
Data DigitalSignatureData `yaml:"data" json:"data"`
Env DigitalSignatureEnv `yaml:"env" json:"env"`
}
type DigitalSignatureData struct {
Key6Dat string `yaml:"Key-6-dat" json:"Key-6-dat"`
AllowedKeysYml string `yaml:"allowed-keys-yml" json:"allowed-keys-yml"`
OsplmIni string `yaml:"osplm.ini" json:"osplm.ini"`
}
type DigitalSignatureEnv struct {
SignKeyDeviceType string `yaml:"sign.key.device-type" json:"sign.key.device-type"`
SignKeyFileIssuer string `yaml:"sign.key.file.issuer" json:"sign.key.file.issuer"`
SignKeyFilePassword string `yaml:"sign.key.file.password" json:"sign.key.file.password"`
SignKeyHardwareDevice string `yaml:"sign.key.hardware.device" json:"sign.key.hardware.device"`
SignKeyHardwarePassword string `yaml:"sign.key.hardware.password" json:"sign.key.hardware.password"`
SignKeyHardwareType string `yaml:"sign.key.hardware.type" json:"sign.key.hardware.type"`
}
func PrepareRegistryKeys(reg KeyManagement, rq *http.Request, secretData map[string]map[string]interface{},
values map[string]interface{}, repoFiles map[string]string) (bool, error) {
if reg.KeyVerificationChanged() {
caCertFl, _, err := rq.FormFile("ca-cert")
if err != nil {
return false, fmt.Errorf("no ca-cert file")
}
caJSONFl, _, err := rq.FormFile("ca-json")
if err != nil {
return false, fmt.Errorf("no ca-json file")
}
if err := setCASecretData(repoFiles, caCertFl, caJSONFl); err != nil {
return false, fmt.Errorf("unable to set ca secret data for registry, err: %w", err)
}
}
if reg.KeyDataChanged() {
ds := DigitalSignature{
Env: DigitalSignatureEnv{
SignKeyDeviceType: reg.KeyDeviceType(),
},
Data: DigitalSignatureData{
AllowedKeysYml: reg.VaultSecretPath(),
},
}
keySecretData := make(map[string]interface{})
if err := setKeySecretDataFromRegistry(reg, rq, keySecretData, &ds); err != nil {
return false, fmt.Errorf("unable to set key vars from registry form, err: %w", err)
}
if err := setAllowedKeysSecretData(reg, keySecretData, &ds); err != nil {
return false, fmt.Errorf("unable to set allowed keys secret data, err: %w", err)
}
secretData[reg.VaultSecretPath()] = keySecretData
values["digital-signature"] = ds
}
return reg.KeyVerificationChanged() || reg.KeyDataChanged(), nil
}
func setCASecretData(repoFiles map[string]string, caCertFl, caJSONFl multipart.File) error {
caCertBytes, err := ioutil.ReadAll(caCertFl)
if err != nil {
return fmt.Errorf("unable to read file, err: %w", err)
}
repoFiles["config/dso/CACertificates.p7b"] = string(caCertBytes)
casJSONBytes, err := ioutil.ReadAll(caJSONFl)
if err != nil {
return fmt.Errorf("unable to read file, err: %w", err)
}
repoFiles["config/dso/CAs.json"] = string(casJSONBytes)
return nil
}
func setKeySecretDataFromRegistry(reg KeyManagement, rq *http.Request,
keySecretData map[string]interface{}, ds *DigitalSignature) error {
if reg.KeyDeviceType() == KeyDeviceTypeFile {
key6Fl, _, err := rq.FormFile("key6")
if err != nil {
return fmt.Errorf("unable to get key6 file, %w", err)
}
key6Bytes, err := ioutil.ReadAll(key6Fl)
if err != nil {
return errors.Wrap(err, "unable to read file")
}
keySecretData["Key-6.dat"] = base64.StdEncoding.EncodeToString(key6Bytes)
keySecretData["sign.key.file.issuer"] = reg.SignKeyIssuer()
keySecretData["sign.key.file.password"] = reg.SignKeyPwd()
ds.Env.SignKeyFileIssuer = reg.VaultSecretPath()
ds.Env.SignKeyFilePassword = reg.VaultSecretPath()
ds.Data.Key6Dat = reg.VaultSecretPath()
} else if reg.KeyDeviceType() == KeyDeviceTypeHardware {
keySecretData["sign.key.hardware.type"] = reg.RemoteType()
keySecretData["sign.key.hardware.device"] = fmt.Sprintf("%s:%s (%s)",
reg.RemoteSerialNumber(), reg.RemoteKeyPort(), reg.RemoteKeyHost())
keySecretData["sign.key.hardware.password"] = reg.RemoteKeyPassword()
keySecretData["osplm.ini"] = reg.INIConfig()
ds.Data.OsplmIni = reg.VaultSecretPath()
ds.Env.SignKeyHardwareDevice = reg.VaultSecretPath()
ds.Env.SignKeyHardwarePassword = reg.VaultSecretPath()
ds.Env.SignKeyHardwareType = reg.VaultSecretPath()
}
return nil
}
func setAllowedKeysSecretData(reg KeyManagement, keySecretData map[string]interface{}, ds *DigitalSignature) error {
allowedKeysIssuer := reg.AllowedKeysIssuer()
allowedKeysSerial := reg.AllowedKeysSerial()
if len(allowedKeysIssuer) > 0 {
var allowedKeysConf allowedKeysConfig
for i := range allowedKeysIssuer {
allowedKeysConf.AllowedKeys = append(allowedKeysConf.AllowedKeys, allowedKey{
Issuer: allowedKeysIssuer[i],
Serial: allowedKeysSerial[i],
})
}
allowedKeysYaml, err := yaml.Marshal(&allowedKeysConf)
if err != nil {
return errors.Wrap(err, "unable to encode allowed keys to yaml")
}
keySecretData["allowed-keys.yml"] = string(allowedKeysYaml)
ds.Data.AllowedKeysYml = reg.VaultSecretPath()
}
return nil
}