Skip to content

Commit 6879f09

Browse files
committed
External Provider Integration Template App - AKV and file renames
1 parent a8cea4f commit 6879f09

6 files changed

Lines changed: 112 additions & 5 deletions

File tree

samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SQL Server BDC Encryption at Rest
22

3-
This folder contains the AppDeploy template application for integration with external key providers (such as HSMs, HashiCorp Vault, etc).
3+
This folder contains the AppDeploy template application for integration with external key providers (such as HSMs, HashiCorp Vault, Azure Key Vault, etc).
44

55
The folder kms_plugin_app should be downloaded as a zip file for usage in respect of the instructions at [External Key Providers](https://docs.microsoft.com/sql/big-data-cluster/encryption-at-rest-external-provider).
66

samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/kms_plugin_app/app.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from constants import ConfigurationConstants, Operations
99
import utils
1010
from json_objects import EncryptDecryptRequest
11-
import custom2
11+
import custom
1212

1313
def handler(operation, payload, pin, key_attributes, version):
1414
"""
@@ -45,16 +45,16 @@ def get_key(json_key_attributes_dict, pin, version):
4545
"""
4646
Call in to the custom key store module to get the key.
4747
"""
48-
return custom2.get_key(json_key_attributes_dict, pin, version)
48+
return custom.get_key(json_key_attributes_dict, pin, version)
4949

5050
def wrap_key(request, json_key_attributes_dict, pin, version):
5151
"""
5252
Call in to the custom key store module to encrypt.
5353
"""
54-
return custom2.encrypt(request, json_key_attributes_dict, pin, version)
54+
return custom.encrypt(request, json_key_attributes_dict, pin, version)
5555

5656
def unwrap_key(request, json_key_attributes_dict, pin, version):
5757
"""
5858
Call in to the custom key store module to decrypt.
5959
"""
60-
return custom2.decrypt(request, json_key_attributes_dict, pin, version)
60+
return custom.decrypt(request, json_key_attributes_dict, pin, version)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Placeholder for adding logic specific to application
2+
# and backend key store.
3+
#
4+
import os
5+
import json
6+
import sys
7+
from azure.identity import DefaultAzureCredential
8+
from azure.keyvault.keys import KeyClient
9+
from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm
10+
# Append the current application path to sys path to be able to resolve local modules.
11+
#
12+
sys.path.append('.')
13+
sys.path.append('./model')
14+
from constants import ConfigurationConstants, Operations, CryptoConstants
15+
import utils
16+
from json_objects import EncryptDecryptRequest, JsonWebKeyResponse, EncryptDecryptResponse
17+
18+
19+
def decrypt(request, json_key_attributes_dict, pin, version):
20+
"""
21+
This method will be called by the application entry point
22+
for decrypting the payload.
23+
request.value has the plaintext payload
24+
request.alg contains the padding algorithm for encryption.
25+
"""
26+
set_env(json_key_attributes_dict, pin)
27+
credential = DefaultAzureCredential()
28+
key_vault_key = get_akv_key(json_key_attributes_dict, credential)
29+
crypto_client = CryptographyClient(key_vault_key, credential=credential)
30+
decrypted_payload = crypto_client.decrypt(EncryptionAlgorithm.rsa_oaep, request.value)
31+
response = EncryptDecryptResponse(decrypted_payload.plaintext)
32+
return response
33+
34+
def encrypt(request, json_key_attributes_dict, pin, version):
35+
"""
36+
This method will be called by the application entry point
37+
for encrypting the payload.
38+
request.value has the plaintext payload
39+
request.alg contains the padding algorithm for encryption.
40+
"""
41+
set_env(json_key_attributes_dict, pin)
42+
credential = DefaultAzureCredential()
43+
key_vault_key = get_akv_key(json_key_attributes_dict, credential)
44+
crypto_client = CryptographyClient(key_vault_key, credential=credential)
45+
encrypted_payload = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep, request.value)
46+
response = EncryptDecryptResponse(encrypted_payload.ciphertext)
47+
return response
48+
49+
def get_key(json_key_attributes_dict, pin, version):
50+
set_env(json_key_attributes_dict, pin)
51+
credential = DefaultAzureCredential()
52+
53+
key_vault_key = get_akv_key(json_key_attributes_dict, credential)
54+
55+
# JsonWebKeyResponse expects integer inputs and converts them to byte array
56+
# However AKV SDK already provides byte arrays for Exponent and Modulus.
57+
# We will instantiate the object with a dummy value and then overwrite the
58+
# exponent and module value.
59+
#
60+
dummy_val = 1
61+
key_response = JsonWebKeyResponse(1,1)
62+
key_response.e = utils.urlsafe_b64encode_as_str(key_vault_key.key.e)
63+
key_response.n = utils.urlsafe_b64encode_as_str(key_vault_key.key.n)
64+
return key_response
65+
66+
def get_akv_key(json_key_attributes_dict, credential):
67+
"""
68+
Gets the AKV key object.
69+
"""
70+
if "vault_url" in json_key_attributes_dict:
71+
vault_url = json_key_attributes_dict["vault_url"]
72+
else:
73+
raise KeyError('vault_url was expected in the parameters but not found')
74+
75+
if "keyname" in json_key_attributes_dict:
76+
key_name = json_key_attributes_dict["keyname"]
77+
else:
78+
raise KeyError('keyname was expected in the parameters but not found')
79+
if "keyversion" in json_key_attributes_dict:
80+
key_version = json_key_attributes_dict["keyversion"]
81+
else:
82+
raise KeyError('keyversion was expected in the parameters but not found')
83+
84+
key_client = KeyClient(vault_url=vault_url, credential=credential)
85+
key_vault_key = key_client.get_key(key_name, key_version)
86+
87+
return key_vault_key
88+
89+
def set_env(json_key_attributes_dict, pin):
90+
"""
91+
Sets the environment variables for the MS identity credential lookup to work.
92+
"""
93+
if "azure_client_id" in json_key_attributes_dict:
94+
key_version = json_key_attributes_dict["azure_client_id"]
95+
else:
96+
raise KeyError('azure_client_id was expected in the parameters but not found')
97+
98+
if "azure_tenant_id" in json_key_attributes_dict:
99+
key_version = json_key_attributes_dict["azure_tenant_id"]
100+
else:
101+
raise KeyError('azure_tenant_id was expected in the parameters but not found')
102+
103+
os.environ["AZURE_CLIENT_ID"]=json_key_attributes_dict["azure_client_id"]
104+
os.environ["AZURE_TENANT_ID"]=json_key_attributes_dict["azure_tenant_id"]
105+
os.environ["AZURE_CLIENT_SECRET"]=pin

samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/kms_plugin_app/custom2.py renamed to samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/kms_plugin_app/custom_hcv.py

File renamed without changes.

samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/kms_plugin_app/custom.py renamed to samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/kms_plugin_app/custom_softhsm.py

File renamed without changes.

samples/features/sql-big-data-cluster/security/encryption-at-rest-external-key-provider/kms_plugin_app/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ pycrypto==2.6.1
22
pycryptodome==3.10.1
33
cryptography==3.2.1
44
hvac==0.10.11
5+
azure-identity==1.6.0
6+
azure-keyvault-keys==4.3.1

0 commit comments

Comments
 (0)