Skip to content

Commit

Permalink
Make SignData work with HC Vault keymanager plugin (spiffe#5058)
Browse files Browse the repository at this point in the history
  • Loading branch information
InverseIntegral committed Aug 22, 2024
1 parent 2a3de21 commit 2a920d1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 16 deletions.
29 changes: 21 additions & 8 deletions pkg/server/plugin/keymanager/hashicorpvault/hashicorp_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package hashicorpvault
import (
"context"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"errors"
Expand All @@ -16,6 +17,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"os"
"strings"
"sync"
)

Expand Down Expand Up @@ -212,14 +214,29 @@ func (p *Plugin) SignData(ctx context.Context, req *keymanagerv1.SignDataRequest
return nil, err
}

signResp, err := p.vc.SignData(ctx, req.KeyId, req.Data, hashAlgo, signingAlgo)
// TODO: Should this be done in SignData?
encodedData := base64.StdEncoding.EncodeToString(req.Data)
signResp, err := p.vc.SignData(ctx, req.KeyId, encodedData, hashAlgo, signingAlgo)

if err != nil {
return nil, status.Errorf(codes.Internal, "failed to sign: %v", err)
}

// TODO: Should this be done in SignData?
sig := signResp.Data["signature"].(string)
cutSig, ok := strings.CutPrefix(sig, "vault:v1:")

if !ok {
return nil, status.Errorf(codes.Internal, "response should contain vault prefix: %v", err)
}

data, err := base64.StdEncoding.DecodeString(cutSig)
if err != nil {
return nil, status.Errorf(codes.Internal, "unable to base64 decode signature: %v", err)
}

return &keymanagerv1.SignDataResponse{
Signature: signResp.Data["signature"].([]byte),
Signature: data,
KeyFingerprint: keyEntry.PublicKey.Fingerprint,
}, nil
}
Expand Down Expand Up @@ -252,8 +269,6 @@ func (p *Plugin) GetPublicKeys(context.Context, *keymanagerv1.GetPublicKeysReque
keys = append(keys, key.PublicKey)
}

p.logger.Debug("getting public keys")

return &keymanagerv1.GetPublicKeysResponse{PublicKeys: keys}, nil
}

Expand Down Expand Up @@ -283,10 +298,8 @@ func algosForKMS(keyType keymanagerv1.KeyType, signerOpts any) (TransitHashAlgor
switch {
case hashAlgo == keymanagerv1.HashAlgorithm_UNSPECIFIED_HASH_ALGORITHM:
return "", "", errors.New("hash algorithm is required")
case keyType == keymanagerv1.KeyType_EC_P256 && hashAlgo == keymanagerv1.HashAlgorithm_SHA256:
return TransitHashAlgorithmSHA256, TransitSignatureSignatureAlgorithmPKCS1v15, nil
case keyType == keymanagerv1.KeyType_EC_P384 && hashAlgo == keymanagerv1.HashAlgorithm_SHA384:
return TransitHashAlgorithmSHA384, TransitSignatureSignatureAlgorithmPKCS1v15, nil
case keyType == keymanagerv1.KeyType_EC_P256 || keyType == keymanagerv1.KeyType_EC_P384:
return TransitHashAlgorithmNone, TransitSignatureSignatureAlgorithmPKCS1v15, nil
case isRSA && !isPSS && hashAlgo == keymanagerv1.HashAlgorithm_SHA256:
return TransitHashAlgorithmSHA256, TransitSignatureSignatureAlgorithmPKCS1v15, nil
case isRSA && !isPSS && hashAlgo == keymanagerv1.HashAlgorithm_SHA384:
Expand Down
18 changes: 10 additions & 8 deletions pkg/server/plugin/keymanager/hashicorpvault/vault_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ const (
TransitHashAlgorithmSHA256 TransitHashAlgorithm = "sha2-256"
TransitHashAlgorithmSHA384 TransitHashAlgorithm = "sha2-384"
TransitHashAlgorithmSHA512 TransitHashAlgorithm = "sha2-512"
TransitHashAlgorithmNone TransitHashAlgorithm = "none"
)

type TransitSignatureAlgorithm string
Expand Down Expand Up @@ -387,15 +388,16 @@ func (c *Client) GetKey(ctx context.Context, spireKeyID string) (*vapi.Secret, e
return c.vaultClient.Logical().ReadWithContext(ctx, fmt.Sprintf("/transit/keys/%s", spireKeyID))
}

func (c *Client) SignData(ctx context.Context, spireKeyID string, data []byte, hashAlgo TransitHashAlgorithm, signatureAlgo TransitSignatureAlgorithm) (*vapi.Secret, error) {
// TODO: Handle errors here
// TODO: Make the transit engine path configurable
return c.vaultClient.Logical().WriteWithContext(ctx, fmt.Sprintf("/transit/sign/%s", spireKeyID), map[string]interface{}{
func (c *Client) SignData(ctx context.Context, spireKeyID string, data string, hashAlgo TransitHashAlgorithm, signatureAlgo TransitSignatureAlgorithm) (*vapi.Secret, error) {
body := map[string]interface{}{
"key_version": "0",
"hash_algorithm": hashAlgo,
"input": data,
"signature_algorithm": signatureAlgo,
"marshalling_algorithm": "asn1", // TODO: Should this be jwt?
"salt_length": "hash", // TODO: Should this be auto or should we let it be configured?
})
"marshalling_algorithm": "asn1",
"prehashed": "true",
}

// TODO: Handle errors here
// TODO: Make the transit engine path configurable
return c.vaultClient.Logical().WriteWithContext(ctx, fmt.Sprintf("/transit/sign/%s/%s", spireKeyID, hashAlgo), body)
}

0 comments on commit 2a920d1

Please sign in to comment.