Skip to content

Instantly share code, notes, and snippets.

@ianf-mongodb
Last active June 29, 2022 20:21
Show Gist options
  • Save ianf-mongodb/7e70c976440234e5577416bf0ce4e955 to your computer and use it in GitHub Desktop.
Save ianf-mongodb/7e70c976440234e5577416bf0ce4e955 to your computer and use it in GitHub Desktop.

These are the source files to build Python sample applications that use CSFLE with the following KMS providers:

  • AWS
  • GCP
  • Azure
  • Local KMS

To build Python applications, run the following command from the parent of this directory:

python build.py --project python

To test your built applications, run the following command from the parent of this directory:

python -m unittest test.TestPython
from pymongo import MongoClient
from pymongo.encryption_options import AutoEncryptionOpts
from pymongo.encryption import ClientEncryption
import base64
import os
from bson.codec_options import CodecOptions
from bson.binary import STANDARD, UUID
import pprint
# start-key-vault
key_vault_namespace = "encryption.__keyVault"
# end-key-vault
# :state-start: aws-test azure-test local-test gcp-test
connection_string = os.getenv("MONGODB_URI")
# :state-end:
# :state-start: local-reader aws-reader azure-reader gcp-reader
# :uncomment-start:
#connection_string = "<your connection string here>"
# :uncomment-end:
# :state-end:
# start-kmsproviders
# :state-start: local-reader local-test
path = "./master-key.txt"
with open(path, "rb") as f:
local_master_key = f.read()
kms_providers = {
"local": {
"key": local_master_key # local_master_key variable from the previous step
},
}
# :state-end:
# :state-uncomment-start: aws-reader
# provider="aws"
# kms_providers = {
# "aws": {
# "accessKeyId": "<IAM User Access Key ID>",
# "secretAccessKey": "<IAM User Secret Access Key>"
# }
# }
# :state-uncomment-end:
# :state-uncomment-start: aws-test
# provider="aws"
# kms_providers = {
# "aws": {
# "accessKeyId": os.getenv("AWS_ACCESS_KEY_ID"),
# "secretAccessKey": os.getenv("AWS_SECRET_ACCESS_KEY")
# }
# }
# :state-uncomment-end:
# :state-uncomment-start: azure-reader
#provider = "azure"
#kms_providers = {
# "azure": {
# "tenantId": "<Azure account organization>",
# "clientId": "<Azure client ID>",
# "clientSecret": "<Azure client secret>",
# }
#}
# :state-uncomment-end:
# :state-uncomment-start: azure-test
#provider = "azure"
#kms_providers = {
# "azure": {
# "tenantId": os.getenv("AZURE_TENANT_ID"),
# "clientId": os.getenv("AZURE_CLIENT_ID"),
# "clientSecret": os.getenv("AZURE_CLIENT_SECRET"),
# }
#}
# :state-uncomment-end:
# :state-uncomment-start: gcp-reader
#provider = "gcp"
#kms_providers = {
# "gcp": {
# "email": "<your GCP email>",
# "privateKey": "<your GCP private key>"
# }
#}
# :state-uncomment-end:
# :state-uncomment-start: gcp-test
#provider = "gcp"
#kms_providers = {
# "gcp": {
# "email": os.getenv("GCP_EMAIL"),
# "privateKey": os.getenv("GCP_PRIVATE_KEY")
# }
#}
# :state-uncomment-end:
# end-kmsproviders
# start-schema
# :state-start: aws-reader azure-reader local-reader gcp-reader
dek_id = b"<paste-base-64-encoded-data-encryption-key-id>"
json_schema = {
"bsonType": "object",
"encryptMetadata": {"keyId": [Binary(base64.b64decode(dek_id), UUID_SUBTYPE)]},
"properties": {
"insurance": {
"bsonType": "object",
"properties": {
"policyNumber": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
}
}
},
},
"medicalRecords": {
"encrypt": {
"bsonType": "array",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
}
},
"bloodType": {
"encrypt": {
"bsonType": "string",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
}
},
"ssn": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
}
},
},
}
patient_schema = {"medicalRecords.patients": json_schema}
# :state-end:
# :state-start: aws-test azure-test local-test gcp-test
# :uncomment-start:
## Make All fields random to use json pointer to reference key-id
#json_schema = {'bsonType': 'object', 'encryptMetadata': {'keyId': '/key-id'}, 'properties': {'insurance': {'bsonType': 'object', 'properties': {'policyNumber': {'encrypt': {'bsonType': 'int', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}}}, 'medicalRecords': {'encrypt': {'bsonType': 'array', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}, 'bloodType': {'encrypt': {'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}, 'ssn': {'encrypt': {'bsonType': 'int', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}}}
# :uncomment-end:
# :state-end:
patient_schema = {
"medicalRecords.patients": json_schema
}
# end-schema
# start-extra-options
# :state-start: aws-reader azure-reader local-reader gcp-reader
# :uncomment-start:
#extra_options = {
# 'mongocryptd_spawn_path': '/usr/local/bin/mongocryptd'
#}
# :uncomment-end:
# :state-end:
# :state-start: aws-test azure-test local-test gcp-test
extra_options = {
'mongocryptd_spawn_path': os.getenv("MONGCRYPTD_PATH")
}
# :state-end:
# end-extra-options
# start-client
fle_opts = AutoEncryptionOpts(
kms_providers,
key_vault_namespace,
schema_map=patient_schema,
**extra_options
)
secureClient = MongoClient(connection_string, auto_encryption_opts=fle_opts)
# end-client
# start-insert
def insert_patient(collection, name, ssn, blood_type, medical_records, policy_number, provider):
insurance = {
'policyNumber': policy_number,
'provider': provider
}
doc = {
'name': name,
'ssn': ssn,
'bloodType': blood_type,
'medicalRecords': medical_records,
'insurance': insurance,
# :state-start: aws-test azure-test local-test gcp-test
# :uncomment-start:
#'key-id': 'demo-data-key'
# :uncomment-end:
# :state-end:
}
collection.insert_one(doc)
medical_record = [{"weight": 180, "bloodPressure": "120/80"}]
insert_patient(secureClient.medicalRecords.patients,
"Jon Doe",
241014209,
"AB+",
medical_record,
123142,
"MaestCare")
# end-insert
regularClient = MongoClient(connection_string)
# start-find
print("Finding a document with regular (non-encrypted) client.")
result = regularClient.medicalRecords.patients.find_one({"name":"Jon Doe"})
pprint.pprint(result)
print("Finding a document with encrypted client, searching on an encrypted field")
# :state-start: local-reader aws-reader azure-reader gcp-reader
# :uncomment-start:
#pprint.pprint(secureClient.medicalRecords.patients.find_one({"ssn":241014209}))
# :uncomment-end:
# :state-end:
# :state-start: local-test aws-test azure-test gcp-test
pprint.pprint(secureClient.medicalRecords.patients.find_one({"name":"Jon Doe"}))
# :state-end:
# end-find
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment