forked from TrueCloudLab/certificates
Redefine uris and set proper type.
URIs will now have the form: - azurekms:name=my-key;vault=my-vault - azurekms:name=my-key;vault=my-vault?version=my-version
This commit is contained in:
parent
656099c4f0
commit
d2581489a3
5 changed files with 184 additions and 66 deletions
|
@ -3,7 +3,7 @@ package azurekms
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"net/url"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
|
"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
|
||||||
|
@ -11,11 +11,10 @@ import (
|
||||||
"github.com/Azure/go-autorest/autorest/date"
|
"github.com/Azure/go-autorest/autorest/date"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/certificates/kms/apiv1"
|
"github.com/smallstep/certificates/kms/apiv1"
|
||||||
"github.com/smallstep/certificates/kms/uri"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
apiv1.Register(apiv1.CloudKMS, func(ctx context.Context, opts apiv1.Options) (apiv1.KeyManager, error) {
|
apiv1.Register(apiv1.AzureKMS, func(ctx context.Context, opts apiv1.Options) (apiv1.KeyManager, error) {
|
||||||
return New(ctx, opts)
|
return New(ctx, opts)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,6 +22,10 @@ func init() {
|
||||||
// Scheme is the scheme used for Azure Key Vault uris.
|
// Scheme is the scheme used for Azure Key Vault uris.
|
||||||
const Scheme = "azurekms"
|
const Scheme = "azurekms"
|
||||||
|
|
||||||
|
// keyIDRegexp is the regular experssion that Key Vault uses for on the kid. We
|
||||||
|
// can extract the vault, name and version of the key.
|
||||||
|
var keyIDRegexp = regexp.MustCompile("^https://([0-9a-zA-Z-]+).vault.azure.net/keys/([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+)$")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
valueTrue = true
|
valueTrue = true
|
||||||
value2048 int32 = 2048
|
value2048 int32 = 2048
|
||||||
|
@ -107,6 +110,16 @@ type KeyVaultClient interface {
|
||||||
|
|
||||||
// KeyVault implements a KMS using Azure Key Vault.
|
// KeyVault implements a KMS using Azure Key Vault.
|
||||||
//
|
//
|
||||||
|
// The URI format used in Azure Key Vault is the following:
|
||||||
|
//
|
||||||
|
// - azurekms:name=key-name;vault=vault-name
|
||||||
|
// - azurekms:name=key-name;vault=vault-name?version=key-version
|
||||||
|
//
|
||||||
|
// The scheme is "azurekms"; "name" is the key name; "vault" is the key vault
|
||||||
|
// name where the key is located; "version" is an optional parameter that
|
||||||
|
// defines the version of they key, if version is not given, the latest one will
|
||||||
|
// be used.
|
||||||
|
//
|
||||||
// TODO(mariano): The implementation is using /services/keyvault/v7.1/keyvault
|
// TODO(mariano): The implementation is using /services/keyvault/v7.1/keyvault
|
||||||
// package, at some point Azure might create a keyvault client with all the
|
// package, at some point Azure might create a keyvault client with all the
|
||||||
// functionality in /sdk/keyvault, we should migrate to that once available.
|
// functionality in /sdk/keyvault, we should migrate to that once available.
|
||||||
|
@ -220,16 +233,12 @@ func (k *KeyVault) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespo
|
||||||
return nil, errors.Wrap(err, "keyVault CreateKey failed")
|
return nil, errors.Wrap(err, "keyVault CreateKey failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
keyURI := uri.New("azurekms", url.Values{
|
|
||||||
"vault": []string{vault},
|
|
||||||
"id": []string{name},
|
|
||||||
}).String()
|
|
||||||
|
|
||||||
publicKey, err := convertKey(resp.Key)
|
publicKey, err := convertKey(resp.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyURI := getKeyName(vault, name, resp)
|
||||||
return &apiv1.CreateKeyResponse{
|
return &apiv1.CreateKeyResponse{
|
||||||
Name: keyURI,
|
Name: keyURI,
|
||||||
PublicKey: publicKey,
|
PublicKey: publicKey,
|
||||||
|
|
|
@ -140,19 +140,19 @@ func TestKeyVault_GetPublicKey(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
{"ok", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
}}, pub, false},
|
}}, pub, false},
|
||||||
{"ok with version", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
{"ok with version", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key?version=my-version",
|
Name: "azurekms:vault=my-vault;name=my-key?version=my-version",
|
||||||
}}, pub, false},
|
}}, pub, false},
|
||||||
{"fail GetKey", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
{"fail GetKey", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=not-found?version=my-version",
|
Name: "azurekms:vault=my-vault;name=not-found?version=my-version",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail vault", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
{"fail vault", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
||||||
Name: "azurekms:vault=;id=not-found?version=my-version",
|
Name: "azurekms:vault=;name=not-found?version=my-version",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail id", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
{"fail id", fields{client}, args{&apiv1.GetPublicKeyRequest{
|
||||||
Name: "azurekms:vault=;id=?version=my-version",
|
Name: "azurekms:vault=;name=?version=my-version",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -244,136 +244,136 @@ func TestKeyVault_CreateKey(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok P-256", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok P-256", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
||||||
ProtectionLevel: apiv1.Software,
|
ProtectionLevel: apiv1.Software,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: ecPub,
|
PublicKey: ecPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok P-256 HSM", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok P-256 HSM", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
||||||
ProtectionLevel: apiv1.HSM,
|
ProtectionLevel: apiv1.HSM,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: ecPub,
|
PublicKey: ecPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok P-256 Default", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok P-256 Default", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: ecPub,
|
PublicKey: ecPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok P-384", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok P-384", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
SignatureAlgorithm: apiv1.ECDSAWithSHA384,
|
SignatureAlgorithm: apiv1.ECDSAWithSHA384,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: ecPub,
|
PublicKey: ecPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok P-521", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok P-521", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
SignatureAlgorithm: apiv1.ECDSAWithSHA512,
|
SignatureAlgorithm: apiv1.ECDSAWithSHA512,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: ecPub,
|
PublicKey: ecPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok RSA 0", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok RSA 0", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
Bits: 0,
|
Bits: 0,
|
||||||
SignatureAlgorithm: apiv1.SHA256WithRSA,
|
SignatureAlgorithm: apiv1.SHA256WithRSA,
|
||||||
ProtectionLevel: apiv1.Software,
|
ProtectionLevel: apiv1.Software,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: rsaPub,
|
PublicKey: rsaPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok RSA 0 HSM", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok RSA 0 HSM", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
Bits: 0,
|
Bits: 0,
|
||||||
SignatureAlgorithm: apiv1.SHA256WithRSAPSS,
|
SignatureAlgorithm: apiv1.SHA256WithRSAPSS,
|
||||||
ProtectionLevel: apiv1.HSM,
|
ProtectionLevel: apiv1.HSM,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: rsaPub,
|
PublicKey: rsaPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok RSA 2048", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok RSA 2048", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
Bits: 2048,
|
Bits: 2048,
|
||||||
SignatureAlgorithm: apiv1.SHA384WithRSA,
|
SignatureAlgorithm: apiv1.SHA384WithRSA,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: rsaPub,
|
PublicKey: rsaPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok RSA 3072", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok RSA 3072", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
Bits: 3072,
|
Bits: 3072,
|
||||||
SignatureAlgorithm: apiv1.SHA512WithRSA,
|
SignatureAlgorithm: apiv1.SHA512WithRSA,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: rsaPub,
|
PublicKey: rsaPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"ok RSA 4096", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"ok RSA 4096", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=my-key",
|
Name: "azurekms:vault=my-vault;name=my-key",
|
||||||
Bits: 4096,
|
Bits: 4096,
|
||||||
SignatureAlgorithm: apiv1.SHA512WithRSAPSS,
|
SignatureAlgorithm: apiv1.SHA512WithRSAPSS,
|
||||||
}}, &apiv1.CreateKeyResponse{
|
}}, &apiv1.CreateKeyResponse{
|
||||||
Name: "azurekms:id=my-key;vault=my-vault",
|
Name: "azurekms:name=my-key;vault=my-vault",
|
||||||
PublicKey: rsaPub,
|
PublicKey: rsaPub,
|
||||||
CreateSignerRequest: apiv1.CreateSignerRequest{
|
CreateSignerRequest: apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:id=my-key;vault=my-vault",
|
SigningKey: "azurekms:name=my-key;vault=my-vault",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{"fail createKey", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail createKey", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=not-found",
|
Name: "azurekms:vault=my-vault;name=not-found",
|
||||||
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail convertKey", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail convertKey", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=not-found",
|
Name: "azurekms:vault=my-vault;name=not-found",
|
||||||
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail name", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail name", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "",
|
Name: "",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail vault", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail vault", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=;id=not-found?version=my-version",
|
Name: "azurekms:vault=;name=not-found?version=my-version",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail id", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail id", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=?version=my-version",
|
Name: "azurekms:vault=my-vault;name=?version=my-version",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail SignatureAlgorithm", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail SignatureAlgorithm", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=not-found",
|
Name: "azurekms:vault=my-vault;name=not-found",
|
||||||
SignatureAlgorithm: apiv1.PureEd25519,
|
SignatureAlgorithm: apiv1.PureEd25519,
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail bit size", fields{client}, args{&apiv1.CreateKeyRequest{
|
{"fail bit size", fields{client}, args{&apiv1.CreateKeyRequest{
|
||||||
Name: "azurekms:vault=my-vault;id=not-found",
|
Name: "azurekms:vault=my-vault;name=not-found",
|
||||||
SignatureAlgorithm: apiv1.SHA384WithRSAPSS,
|
SignatureAlgorithm: apiv1.SHA384WithRSAPSS,
|
||||||
Bits: 1024,
|
Bits: 1024,
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
|
@ -426,7 +426,7 @@ func TestKeyVault_CreateSigner(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", fields{client}, args{&apiv1.CreateSignerRequest{
|
{"ok", fields{client}, args{&apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:vault=my-vault;id=my-key",
|
SigningKey: "azurekms:vault=my-vault;name=my-key",
|
||||||
}}, &Signer{
|
}}, &Signer{
|
||||||
client: client,
|
client: client,
|
||||||
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
||||||
|
@ -435,7 +435,7 @@ func TestKeyVault_CreateSigner(t *testing.T) {
|
||||||
publicKey: pub,
|
publicKey: pub,
|
||||||
}, false},
|
}, false},
|
||||||
{"ok with version", fields{client}, args{&apiv1.CreateSignerRequest{
|
{"ok with version", fields{client}, args{&apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:vault=my-vault;id=my-key;version=my-version",
|
SigningKey: "azurekms:vault=my-vault;name=my-key;version=my-version",
|
||||||
}}, &Signer{
|
}}, &Signer{
|
||||||
client: client,
|
client: client,
|
||||||
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
||||||
|
@ -444,7 +444,7 @@ func TestKeyVault_CreateSigner(t *testing.T) {
|
||||||
publicKey: pub,
|
publicKey: pub,
|
||||||
}, false},
|
}, false},
|
||||||
{"fail GetKey", fields{client}, args{&apiv1.CreateSignerRequest{
|
{"fail GetKey", fields{client}, args{&apiv1.CreateSignerRequest{
|
||||||
SigningKey: "azurekms:vault=my-vault;id=not-found;version=my-version",
|
SigningKey: "azurekms:vault=my-vault;name=not-found;version=my-version",
|
||||||
}}, nil, true},
|
}}, nil, true},
|
||||||
{"fail SigningKey", fields{client}, args{&apiv1.CreateSignerRequest{
|
{"fail SigningKey", fields{client}, args{&apiv1.CreateSignerRequest{
|
||||||
SigningKey: "",
|
SigningKey: "",
|
||||||
|
|
|
@ -44,24 +44,24 @@ func TestNewSigner(t *testing.T) {
|
||||||
want crypto.Signer
|
want crypto.Signer
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok", args{client, "azurekms:vault=my-vault;id=my-key"}, &Signer{
|
{"ok", args{client, "azurekms:vault=my-vault;name=my-key"}, &Signer{
|
||||||
client: client,
|
client: client,
|
||||||
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
||||||
name: "my-key",
|
name: "my-key",
|
||||||
version: "",
|
version: "",
|
||||||
publicKey: pub,
|
publicKey: pub,
|
||||||
}, false},
|
}, false},
|
||||||
{"ok with version", args{client, "azurekms:id=my-key;vault=my-vault?version=my-version"}, &Signer{
|
{"ok with version", args{client, "azurekms:name=my-key;vault=my-vault?version=my-version"}, &Signer{
|
||||||
client: client,
|
client: client,
|
||||||
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
vaultBaseURL: "https://my-vault.vault.azure.net/",
|
||||||
name: "my-key",
|
name: "my-key",
|
||||||
version: "my-version",
|
version: "my-version",
|
||||||
publicKey: pub,
|
publicKey: pub,
|
||||||
}, false},
|
}, false},
|
||||||
{"fail GetKey", args{client, "azurekms:id=not-found;vault=my-vault?version=my-version"}, nil, true},
|
{"fail GetKey", args{client, "azurekms:name=not-found;vault=my-vault?version=my-version"}, nil, true},
|
||||||
{"fail vault", args{client, "azurekms:id=not-found;vault="}, nil, true},
|
{"fail vault", args{client, "azurekms:name=not-found;vault="}, nil, true},
|
||||||
{"fail id", args{client, "azurekms:id=;vault=my-vault?version=my-version"}, nil, true},
|
{"fail id", args{client, "azurekms:name=;vault=my-vault?version=my-version"}, nil, true},
|
||||||
{"fail scheme", args{client, "kms:id=not-found;vault=my-vault?version=my-version"}, nil, true},
|
{"fail scheme", args{client, "kms:name=not-found;vault=my-vault?version=my-version"}, nil, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
|
"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
|
||||||
|
@ -17,9 +18,34 @@ func defaultContext() (context.Context, context.CancelFunc) {
|
||||||
return context.WithTimeout(context.Background(), 15*time.Second)
|
return context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseKeyName returns the key vault, name and version for urls like
|
// getKeyName returns the uri of the key vault key.
|
||||||
// azurekms:vault=key-vault;id=key-name?version=key-version. If version is not
|
func getKeyName(vault, name string, bundle keyvault.KeyBundle) string {
|
||||||
// passed the latest version will be used.
|
if bundle.Key != nil && bundle.Key.Kid != nil {
|
||||||
|
sm := keyIDRegexp.FindAllStringSubmatch(*bundle.Key.Kid, 1)
|
||||||
|
if len(sm) == 1 && len(sm[0]) == 4 {
|
||||||
|
m := sm[0]
|
||||||
|
u := uri.New(Scheme, url.Values{
|
||||||
|
"vault": []string{m[1]},
|
||||||
|
"name": []string{m[2]},
|
||||||
|
})
|
||||||
|
u.RawQuery = url.Values{"version": []string{m[3]}}.Encode()
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback to URI without id.
|
||||||
|
return uri.New(Scheme, url.Values{
|
||||||
|
"vault": []string{vault},
|
||||||
|
"name": []string{name},
|
||||||
|
}).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseKeyName returns the key vault, name and version from URIs like:
|
||||||
|
//
|
||||||
|
// - azurekms:vault=key-vault;name=key-name
|
||||||
|
// - azurekms:vault=key-vault;name=key-name;id=key-id
|
||||||
|
//
|
||||||
|
// The key-id defines the version of the key, if it is not passed the latest
|
||||||
|
// version will be used.
|
||||||
func parseKeyName(rawURI string) (vault, name, version string, err error) {
|
func parseKeyName(rawURI string) (vault, name, version string, err error) {
|
||||||
var u *uri.URI
|
var u *uri.URI
|
||||||
|
|
||||||
|
@ -27,13 +53,13 @@ func parseKeyName(rawURI string) (vault, name, version string, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if name = u.Get("name"); name == "" {
|
||||||
if vault = u.Get("vault"); vault == "" {
|
err = errors.Errorf("key uri %s is not valid: name is missing", rawURI)
|
||||||
err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if name = u.Get("id"); name == "" {
|
if vault = u.Get("vault"); vault == "" {
|
||||||
err = errors.Errorf("key uri %s is not valid: id is missing", rawURI)
|
err = errors.Errorf("key uri %s is not valid: vault is missing", rawURI)
|
||||||
|
name = ""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
version = u.Get("version")
|
version = u.Get("version")
|
||||||
|
|
83
kms/azurekms/utils_test.go
Normal file
83
kms/azurekms/utils_test.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package azurekms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_getKeyName(t *testing.T) {
|
||||||
|
getBundle := func(kid string) keyvault.KeyBundle {
|
||||||
|
return keyvault.KeyBundle{
|
||||||
|
Key: &keyvault.JSONWebKey{
|
||||||
|
Kid: &kid,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
vault string
|
||||||
|
name string
|
||||||
|
bundle keyvault.KeyBundle
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"ok", args{"my-vault", "my-key", getBundle("https://my-vault.vault.azure.net/keys/my-key/my-version")}, "azurekms:name=my-key;vault=my-vault?version=my-version"},
|
||||||
|
{"ok default", args{"my-vault", "my-key", getBundle("https://my-vault.foo.net/keys/my-key/my-version")}, "azurekms:name=my-key;vault=my-vault"},
|
||||||
|
{"ok too short", args{"my-vault", "my-key", getBundle("https://my-vault.vault.azure.net/keys/my-version")}, "azurekms:name=my-key;vault=my-vault"},
|
||||||
|
{"ok too long", args{"my-vault", "my-key", getBundle("https://my-vault.vault.azure.net/keys/my-key/my-version/sign")}, "azurekms:name=my-key;vault=my-vault"},
|
||||||
|
{"ok nil key", args{"my-vault", "my-key", keyvault.KeyBundle{}}, "azurekms:name=my-key;vault=my-vault"},
|
||||||
|
{"ok nil kid", args{"my-vault", "my-key", keyvault.KeyBundle{Key: &keyvault.JSONWebKey{}}}, "azurekms:name=my-key;vault=my-vault"},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := getKeyName(tt.args.vault, tt.args.name, tt.args.bundle); got != tt.want {
|
||||||
|
t.Errorf("getKeyName() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parseKeyName(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
rawURI string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantVault string
|
||||||
|
wantName string
|
||||||
|
wantVersion string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"ok", args{"azurekms:name=my-key;vault=my-vault?version=my-version"}, "my-vault", "my-key", "my-version", false},
|
||||||
|
{"ok no version", args{"azurekms:name=my-key;vault=my-vault"}, "my-vault", "my-key", "", false},
|
||||||
|
{"fail scheme", args{"azure:name=my-key;vault=my-vault"}, "", "", "", true},
|
||||||
|
{"fail parse uri", args{"azurekms:name=%ZZ;vault=my-vault"}, "", "", "", true},
|
||||||
|
{"fail no name", args{"azurekms:vault=my-vault"}, "", "", "", true},
|
||||||
|
{"fail empty name", args{"azurekms:name=;vault=my-vault"}, "", "", "", true},
|
||||||
|
{"fail no vault", args{"azurekms:name=my-key"}, "", "", "", true},
|
||||||
|
{"fail empty vault", args{"azurekms:name=my-key;vault="}, "", "", "", true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
gotVault, gotName, gotVersion, err := parseKeyName(tt.args.rawURI)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("parseKeyName() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gotVault != tt.wantVault {
|
||||||
|
t.Errorf("parseKeyName() gotVault = %v, want %v", gotVault, tt.wantVault)
|
||||||
|
}
|
||||||
|
if gotName != tt.wantName {
|
||||||
|
t.Errorf("parseKeyName() gotName = %v, want %v", gotName, tt.wantName)
|
||||||
|
}
|
||||||
|
if gotVersion != tt.wantVersion {
|
||||||
|
t.Errorf("parseKeyName() gotVersion = %v, want %v", gotVersion, tt.wantVersion)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue