Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Azure/kubernetes-kms
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d29f48bdaa96c8217a73f11b4bd8716e790cfcd7
Choose a base ref
..
head repository: Azure/kubernetes-kms
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ea3dd5adae1b5bff47e6f25d36762ee88c7457f7
Choose a head ref
Showing with 77 additions and 64 deletions.
  1. +3 −0 .gitignore
  2. +13 −17 cmd/server/main.go
  3. +51 −36 pkg/plugin/keyvault.go
  4. +2 −2 pkg/plugin/keyvault_test.go
  5. +8 −9 pkg/plugin/server.go
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -31,3 +31,6 @@ tests/e2e/generated_manifests/*

# Go tools
.tools/

# Some tests
pkg/plugin/keyvault1_test.go
30 changes: 13 additions & 17 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -34,13 +34,11 @@ var (
listenAddr = flag.String("listen-addr", "unix:///opt/azurekms.socket", "gRPC listen address")
keyvaultName = flag.String("keyvault-name", "", "Azure Key Vault name")
keyName = flag.String("key-name", "", "Azure Key Vault KMS key name")
keyVersion = flag.String("key-version", "", "Azure Key Vault KMS key version")
// keyVersion and keyVersionlessEnabled are not mutually exclusive for compatibility.
// When keyVersionlessEnabled is enabled on an existing-KMS cluster, only new secrets will be encrypted with versionless key.
keyVersionlessEnabled = flag.Bool("key-versionless-enabled", false, "Azure Key Vault KMS key versionless enabled")
managedHSM = flag.Bool("managed-hsm", false, "Azure Key Vault Managed HSM. Refer to https://docs.microsoft.com/en-us/azure/key-vault/managed-hsm/overview for more details.")
logFormatJSON = flag.Bool("log-format-json", false, "set log formatter to json")
logLevel = flag.Int("v", 0, "In order of increasing verbosity: 0=warning/error, 2=info, 4=debug, 6=trace, 10=all")
// If --key-version not set or is empty, the plugin will use the latest version of the key.
keyVersion = flag.String("key-version", "", "Azure Key Vault KMS key version")
managedHSM = flag.Bool("managed-hsm", false, "Azure Key Vault Managed HSM. Refer to https://docs.microsoft.com/en-us/azure/key-vault/managed-hsm/overview for more details.")
logFormatJSON = flag.Bool("log-format-json", false, "set log formatter to json")
logLevel = flag.Int("v", 0, "In order of increasing verbosity: 0=warning/error, 2=info, 4=debug, 6=trace, 10=all")
// TODO remove this flag in future release.
_ = flag.String("configFilePath", "/etc/kubernetes/azure.json", "[DEPRECATED] Path for Azure Cloud Provider config file")
configFilePath = flag.String("config-file-path", "/etc/kubernetes/azure.json", "Path for Azure Cloud Provider config file")
@@ -93,15 +91,14 @@ func setupKMSPlugin() error {
mlog.Always("Starting KeyManagementServiceServer service", "version", version.BuildVersion, "buildDate", version.BuildDate)

pluginConfig := &plugin.Config{
KeyVaultName: *keyvaultName,
KeyName: *keyName,
KeyVersion: *keyVersion,
KeyVersionlessEnabled: *keyVersionlessEnabled,
ManagedHSM: *managedHSM,
ProxyMode: *proxyMode,
ProxyAddress: *proxyAddress,
ProxyPort: *proxyPort,
ConfigFilePath: *configFilePath,
KeyVaultName: *keyvaultName,
KeyName: *keyName,
KeyVersion: *keyVersion,
ManagedHSM: *managedHSM,
ProxyMode: *proxyMode,
ProxyAddress: *proxyAddress,
ProxyPort: *proxyPort,
ConfigFilePath: *configFilePath,
}

azureConfig, err := config.GetAzureConfig(pluginConfig.ConfigFilePath)
@@ -114,7 +111,6 @@ func setupKMSPlugin() error {
pluginConfig.KeyVaultName,
pluginConfig.KeyName,
pluginConfig.KeyVersion,
pluginConfig.KeyVersionlessEnabled,
pluginConfig.ProxyMode,
pluginConfig.ProxyAddress,
pluginConfig.ProxyPort,
87 changes: 51 additions & 36 deletions pkg/plugin/keyvault.go
Original file line number Diff line number Diff line change
@@ -65,22 +65,20 @@ type Client interface {

// KeyVaultClient is a client for interacting with Keyvault.
type KeyVaultClient struct {
baseClient kv.BaseClient
config *config.AzureConfig
vaultName string
keyName string
keyVersion string
keyVersionlessEnabled bool
vaultURL string
keyIDHash string
azureEnvironment *azure.Environment
baseClient kv.BaseClient
config *config.AzureConfig
vaultName string
keyName string
keyVersion string
vaultURL string
keyIDHash string // keyIDHash is used when key version-less is disabled
azureEnvironment *azure.Environment
}

// NewKeyVaultClient returns a new key vault client to use for kms operations.
func NewKeyVaultClient(
config *config.AzureConfig,
vaultName, keyName, keyVersion string,
keyVersionlessEnabled bool,
proxyMode bool,
proxyAddress string,
proxyPort int,
@@ -93,8 +91,8 @@ func NewKeyVaultClient(

// this should be the case for bring your own key, clusters bootstrapped with
// aks-engine or aks and standalone kms plugin deployments
if len(vaultName) == 0 || len(keyName) == 0 || (!keyVersionlessEnabled && len(keyVersion) == 0) {
return nil, fmt.Errorf("key vault name, key name and key version (not key versionless enabled) are required")
if len(vaultName) == 0 || len(keyName) == 0 {
return nil, fmt.Errorf("key vault name and key name are required")
}

kvClient := kv.New()
@@ -125,7 +123,7 @@ func NewKeyVaultClient(
return nil, fmt.Errorf("failed to get vault url, error: %+v", err)
}

var keyIDHash string
keyIDHash := ""
if len(keyVersion) != 0 {
keyIDHash, err = getKeyIDHash(*vaultURL, keyName, keyVersion)
if err != nil {
@@ -141,15 +139,14 @@ func NewKeyVaultClient(
mlog.Always("using kms key for encrypt/decrypt", "vaultURL", *vaultURL, "keyName", keyName, "keyVersion", keyVersion)

client := &KeyVaultClient{
baseClient: kvClient,
config: config,
vaultName: vaultName,
keyName: keyName,
keyVersion: keyVersion,
keyVersionlessEnabled: keyVersionlessEnabled,
vaultURL: *vaultURL,
azureEnvironment: env,
keyIDHash: keyIDHash,
baseClient: kvClient,
config: config,
vaultName: vaultName,
keyName: keyName,
keyVersion: keyVersion,
vaultURL: *vaultURL,
azureEnvironment: env,
keyIDHash: keyIDHash,
}
return client, nil
}
@@ -168,31 +165,37 @@ func (kvc *KeyVaultClient) Encrypt(
}

keyVersion := kvc.keyVersion
if kvc.keyVersionlessEnabled {
keyVersion = ""
}

result, err := kvc.baseClient.Encrypt(ctx, kvc.vaultURL, kvc.keyName, keyVersion, params)
if err != nil {
return nil, fmt.Errorf("failed to encrypt, error: %+v", err)
}

keyIDHash := ""
if kvc.keyVersionlessEnabled {
if result.Kid == nil {
return nil, fmt.Errorf("key id is nil in encryption result")
if result.Kid == nil {
return nil, fmt.Errorf("key id is nil in encryption result")
}
if len(keyVersion) == 0 {
keyVersion = path.Base(strings.TrimSuffix(*result.Kid, "/"))
keyIDHash, err = getKeyIDHash(kvc.vaultURL, kvc.keyName, keyVersion)
if err != nil {
return nil, fmt.Errorf("failed to get key id hash, error: %w", err)
}
kidSplitted := strings.Split(*result.Kid, "/")
keyVersion = kidSplitted[len(kidSplitted)-1]
} else {
keyIDHash = kvc.keyIDHash
if keyIDHash != fmt.Sprintf("%x", sha256.Sum256([]byte(*result.Kid))) {
return nil, fmt.Errorf(
"key id initialized does not match with the key id from encryption result, expected: %s, got: %s",
keyIDHash,
*result.Kid,
)
}
} else {
if kvc.keyIDHash != fmt.Sprintf("%x", sha256.Sum256([]byte(*result.Kid))) {
return nil, fmt.Errorf(
"key id initialized does not match with the key id from encryption result, expected: %s, got: %s",
kvc.keyIDHash,
*result.Kid,
)
}
keyIDHash = kvc.keyIDHash
}

annotations := map[string][]byte{
@@ -266,21 +269,33 @@ func (kvc *KeyVaultClient) GetVaultURL() string {
// It also validates keyID that the API server checks.
func (kvc *KeyVaultClient) validateAnnotations(
annotations map[string][]byte,
keyID string,
keyIDHash string,
encryptionAlgorithm kv.JSONWebKeyEncryptionAlgorithm,
) error {
if len(annotations) == 0 {
return fmt.Errorf("invalid annotations, annotations cannot be empty")
}

if len(annotations[keyVersionAnnotationKey]) == 0 {
if keyID != kvc.keyIDHash {
if keyIDHash != kvc.keyIDHash {
return fmt.Errorf(
"key id %s does not match expected key id %s used for encryption",
keyID,
keyIDHash,
kvc.keyIDHash,
)
}
} else {
keyIDHashLocal, err := getKeyIDHash(kvc.vaultURL, kvc.keyName, string(annotations[keyVersionAnnotationKey]))
if err != nil {
return fmt.Errorf("failed to get key id hash, error: %w", err)
}
if keyIDHashLocal != keyIDHash {
return fmt.Errorf(
"key id %s does not match expected key id %s used for encryption",
keyIDHash,
keyIDHashLocal,
)
}
}

algorithm := string(annotations[algorithmAnnotationKey])
4 changes: 2 additions & 2 deletions pkg/plugin/keyvault_test.go
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ func TestNewKeyVaultClientError(t *testing.T) {

for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
if _, err := NewKeyVaultClient(test.config, test.vaultName, test.keyName, test.keyVersion, test.keyVersionlessEnabled, test.proxyMode, test.proxyAddress, test.proxyPort, test.managedHSM); err == nil {
if _, err := NewKeyVaultClient(test.config, test.vaultName, test.keyName, test.keyVersion, test.proxyMode, test.proxyAddress, test.proxyPort, test.managedHSM); err == nil {
t.Fatalf("newKeyVaultClient() expected error, got nil")
}
})
@@ -143,7 +143,7 @@ func TestNewKeyVaultClient(t *testing.T) {

for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
kvClient, err := NewKeyVaultClient(test.config, test.vaultName, test.keyName, test.keyVersion, test.keyVersionlessEnabled, test.proxyMode, test.proxyAddress, test.proxyPort, test.managedHSM)
kvClient, err := NewKeyVaultClient(test.config, test.vaultName, test.keyName, test.keyVersion, test.proxyMode, test.proxyAddress, test.proxyPort, test.managedHSM)
if err != nil {
t.Fatalf("newKeyVaultClient() failed with error: %v", err)
}
17 changes: 8 additions & 9 deletions pkg/plugin/server.go
Original file line number Diff line number Diff line change
@@ -27,15 +27,14 @@ type KeyManagementServiceServer struct {

// Config is the configuration for the KMS plugin.
type Config struct {
ConfigFilePath string
KeyVaultName string
KeyName string
KeyVersion string
KeyVersionlessEnabled bool
ManagedHSM bool
ProxyMode bool
ProxyAddress string
ProxyPort int
ConfigFilePath string
KeyVaultName string
KeyName string
KeyVersion string
ManagedHSM bool
ProxyMode bool
ProxyAddress string
ProxyPort int
}

// NewKMSv1Server creates an instance of the KMS Service Server.