Search in sources :

Example 1 with EncryptOptions

use of com.mongodb.client.model.vault.EncryptOptions in project mongo-java-driver by mongodb.

the class ClientEncryptionDataKeyAndDoubleEncryptionTest method testProvider.

@Test
public void testProvider() {
    String keyAltName = format("%s_altname", providerName);
    BsonBinary dataKeyId = clientEncryption.createDataKey(providerName, new DataKeyOptions().keyAltNames(singletonList(keyAltName)).masterKey(getMasterKey()));
    assertEquals(4, dataKeyId.getType());
    ArrayList<Document> dataKeys = client.getDatabase("keyvault").getCollection("datakeys").find(eq("_id", dataKeyId)).into(new ArrayList<>());
    assertEquals(1, dataKeys.size());
    Document dataKey = dataKeys.get(0);
    assertEquals(providerName, dataKey.get("masterKey", new Document()).get("provider", ""));
    String insertWriteConcern = commandListener.getCommandStartedEvent("insert").getCommand().getDocument("writeConcern", new BsonDocument()).getString("w", new BsonString("")).getValue();
    assertEquals("majority", insertWriteConcern);
    String stringToEncrypt = format("hello %s", providerName);
    BsonBinary encrypted = clientEncryption.encrypt(new BsonString(stringToEncrypt), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
    assertEquals(6, encrypted.getType());
    Document insertDocument = new Document("_id", providerName);
    insertDocument.put("value", encrypted);
    clientEncrypted.getDatabase("db").getCollection("coll").insertOne(insertDocument);
    Document decryptedDocument = clientEncrypted.getDatabase("db").getCollection("coll").find(eq("_id", providerName)).first();
    assertNotNull(decryptedDocument);
    assertEquals(stringToEncrypt, decryptedDocument.get("value", ""));
    BsonBinary encryptedKeyAltName = clientEncryption.encrypt(new BsonString(stringToEncrypt), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyAltName(keyAltName));
    assertEquals(encrypted, encryptedKeyAltName);
    assertThrows(MongoClientException.class, () -> clientEncrypted.getDatabase("db").getCollection("coll").insertOne(new Document("encrypted_placeholder", encrypted)));
}
Also used : BsonDocument(org.bson.BsonDocument) EncryptOptions(com.mongodb.client.model.vault.EncryptOptions) BsonBinary(org.bson.BsonBinary) BsonString(org.bson.BsonString) BsonString(org.bson.BsonString) Document(org.bson.Document) BsonDocument(org.bson.BsonDocument) DataKeyOptions(com.mongodb.client.model.vault.DataKeyOptions) Test(org.junit.Test)

Example 2 with EncryptOptions

use of com.mongodb.client.model.vault.EncryptOptions in project mongo-java-driver by mongodb.

the class ClientSideEncryptionCorpusTest method testCorpus.

@Test
public void testCorpus() throws IOException, URISyntaxException {
    // Step 5: Iterate over corpus
    BsonDocument corpus = bsonDocumentFromPath("corpus.json");
    BsonDocument corpusCopied = new BsonDocument();
    for (String field : corpus.keySet()) {
        if (!corpus.get(field).isDocument()) {
            corpusCopied.append(field, corpus.get(field));
            continue;
        }
        BsonDocument fieldDocument = corpus.getDocument(field).clone();
        String kms = fieldDocument.getString("kms").getValue();
        String abbreviatedAlgorithName = fieldDocument.getString("algo").getValue();
        String method = fieldDocument.getString("method").getValue();
        String identifier = fieldDocument.getString("identifier").getValue();
        boolean allowed = fieldDocument.getBoolean("allowed").getValue();
        BsonValue value = fieldDocument.get("value");
        byte[] awsKeyId = Base64.getDecoder().decode("AWSAAAAAAAAAAAAAAAAAAA==");
        byte[] azureKeyId = Base64.getDecoder().decode("AZUREAAAAAAAAAAAAAAAAA==");
        byte[] gcpKeyId = Base64.getDecoder().decode("GCPAAAAAAAAAAAAAAAAAAA==");
        byte[] kmipKeyId = Base64.getDecoder().decode("KMIPAAAAAAAAAAAAAAAAAA==");
        byte[] localKeyId = Base64.getDecoder().decode("LOCALAAAAAAAAAAAAAAAAA==");
        if (method.equals("auto")) {
            corpusCopied.append(field, corpus.get(field));
            continue;
        }
        if (!method.equals("explicit")) {
            throw new UnsupportedOperationException("Unsupported method: " + method);
        }
        String fullAlgorithmName = "AEAD_AES_256_CBC_HMAC_SHA_512-";
        if (abbreviatedAlgorithName.equals("rand")) {
            fullAlgorithmName += "Random";
        } else if (abbreviatedAlgorithName.equals("det")) {
            fullAlgorithmName += "Deterministic";
        } else {
            throw new UnsupportedOperationException("Unsupported algorithm: " + abbreviatedAlgorithName);
        }
        EncryptOptions opts = new EncryptOptions(fullAlgorithmName);
        if (identifier.equals("id")) {
            switch(kms) {
                case "aws":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, awsKeyId));
                    break;
                case "azure":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, azureKeyId));
                    break;
                case "gcp":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, gcpKeyId));
                    break;
                case "kmip":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, kmipKeyId));
                    break;
                case "local":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, localKeyId));
                    break;
                default:
                    throw new UnsupportedOperationException("Unsupported provider: " + kms);
            }
        } else if (identifier.equals("altname")) {
            opts.keyAltName(kms);
        } else {
            throw new UnsupportedOperationException("Unsupported identifier: " + identifier);
        }
        try {
            BsonValue encryptedValue = clientEncryption.encrypt(value, opts);
            fieldDocument.put("value", encryptedValue);
            corpusCopied.append(field, fieldDocument);
        } catch (MongoException e) {
            if (allowed) {
                throw e;
            }
            corpusCopied.append(field, fieldDocument);
        }
    }
    // Step 6: insert corpusCopied
    MongoCollection<BsonDocument> encryptedCollection = autoEncryptingClient.getDatabase("db").getCollection("coll", BsonDocument.class);
    encryptedCollection.insertOne(corpusCopied);
    // Step 7: check the auto decrypted document
    BsonDocument corpusDecrypted = encryptedCollection.find(new BsonDocument()).first();
    assertEquals(corpus, corpusDecrypted);
    // Step 8: check the document with an unencrypted client
    MongoCollection<BsonDocument> coll = client.getDatabase("db").getCollection("coll", BsonDocument.class);
    BsonDocument corpusEncryptedActual = coll.find(new BsonDocument()).first();
    BsonDocument corpusEncryptedExpected = bsonDocumentFromPath("corpus-encrypted.json");
    for (String field : corpusEncryptedExpected.keySet()) {
        if (field.equals("_id") || field.equals("altname_aws") || field.equals("altname_local")) {
            continue;
        }
        boolean allowed = corpusEncryptedActual.getDocument(field).getBoolean("allowed").getValue();
        String algorithm = corpusEncryptedActual.getDocument(field).getString("algo").getValue();
        BsonValue actualValue = corpusEncryptedActual.getDocument(field).get("value");
        BsonValue expectedValue = corpusEncryptedExpected.getDocument(field).get("value");
        if (algorithm.equals("det")) {
            assertEquals(actualValue, expectedValue);
        } else if (algorithm.equals("rand")) {
            if (allowed) {
                assertNotEquals(actualValue, expectedValue);
            }
        } else {
            throw new UnsupportedOperationException("Unsupported algorithm type: " + algorithm);
        }
        if (allowed) {
            BsonValue decrypted = clientEncryption.decrypt(actualValue.asBinary());
            assertEquals("Values should be equal for field " + field, clientEncryption.decrypt(expectedValue.asBinary()), decrypted);
        } else {
            assertEquals("Values should be equal for field " + field, expectedValue, actualValue);
        }
    }
}
Also used : MongoException(com.mongodb.MongoException) BsonDocument(org.bson.BsonDocument) EncryptOptions(com.mongodb.client.model.vault.EncryptOptions) BsonBinary(org.bson.BsonBinary) BsonString(org.bson.BsonString) BsonValue(org.bson.BsonValue) Test(org.junit.Test)

Example 3 with EncryptOptions

use of com.mongodb.client.model.vault.EncryptOptions in project mongo-java-driver by mongodb.

the class ClientSideEncryptionExternalKeyVaultTest method testExternal.

@Test
public void testExternal() {
    boolean authExceptionThrown = false;
    MongoCollection<BsonDocument> coll = clientEncrypted.getDatabase("db").getCollection("coll", BsonDocument.class);
    try {
        coll.insertOne(new BsonDocument().append("encrypted", new BsonString("test")));
    } catch (MongoSecurityException mse) {
        authExceptionThrown = true;
    }
    assertEquals(authExceptionThrown, withExternalKeyVault);
    EncryptOptions encryptOptions = new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("LOCALAAAAAAAAAAAAAAAAA==")));
    authExceptionThrown = false;
    try {
        clientEncryption.encrypt(new BsonString("test"), encryptOptions);
    } catch (MongoSecurityException mse) {
        authExceptionThrown = true;
    }
    assertEquals(authExceptionThrown, withExternalKeyVault);
}
Also used : MongoSecurityException(com.mongodb.MongoSecurityException) BsonDocument(org.bson.BsonDocument) EncryptOptions(com.mongodb.client.model.vault.EncryptOptions) BsonString(org.bson.BsonString) BsonBinary(org.bson.BsonBinary) Test(org.junit.Test) ClusterFixture.isClientSideEncryptionTest(com.mongodb.ClusterFixture.isClientSideEncryptionTest)

Example 4 with EncryptOptions

use of com.mongodb.client.model.vault.EncryptOptions in project mongo-java-driver by mongodb.

the class ClientEncryptionDataKeyAndDoubleEncryptionTest method testProvider.

@Test
public void testProvider() {
    String keyAltName = format("%s_altname", providerName);
    BsonBinary dataKeyId = clientEncryption.createDataKey(providerName, new DataKeyOptions().keyAltNames(singletonList(keyAltName)).masterKey(getMasterKey()));
    assertEquals(4, dataKeyId.getType());
    ArrayList<Document> dataKeys = client.getDatabase("keyvault").getCollection("datakeys").find(eq("_id", dataKeyId)).into(new ArrayList<>());
    assertEquals(1, dataKeys.size());
    Document dataKey = dataKeys.get(0);
    assertEquals(providerName, dataKey.get("masterKey", new Document()).get("provider", ""));
    String insertWriteConcern = commandListener.getCommandStartedEvent("insert").getCommand().getDocument("writeConcern", new BsonDocument()).getString("w", new BsonString("")).getValue();
    assertEquals("majority", insertWriteConcern);
    String stringToEncrypt = format("hello %s", providerName);
    BsonBinary encrypted = clientEncryption.encrypt(new BsonString(stringToEncrypt), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
    assertEquals(6, encrypted.getType());
    Document insertDocument = new Document("_id", providerName);
    insertDocument.put("value", encrypted);
    clientEncrypted.getDatabase("db").getCollection("coll").insertOne(insertDocument);
    Document decryptedDocument = clientEncrypted.getDatabase("db").getCollection("coll").find(eq("_id", providerName)).first();
    assertNotNull(decryptedDocument);
    assertEquals(stringToEncrypt, decryptedDocument.get("value", ""));
    BsonBinary encryptedKeyAltName = clientEncryption.encrypt(new BsonString(stringToEncrypt), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyAltName(keyAltName));
    assertEquals(encrypted, encryptedKeyAltName);
    assertThrows(MongoClientException.class, () -> clientEncrypted.getDatabase("db").getCollection("coll").insertOne(new Document("encrypted_placeholder", encrypted)));
}
Also used : BsonDocument(org.bson.BsonDocument) EncryptOptions(com.mongodb.client.model.vault.EncryptOptions) BsonBinary(org.bson.BsonBinary) BsonString(org.bson.BsonString) BsonString(org.bson.BsonString) Document(org.bson.Document) BsonDocument(org.bson.BsonDocument) DataKeyOptions(com.mongodb.client.model.vault.DataKeyOptions) Test(org.junit.Test)

Example 5 with EncryptOptions

use of com.mongodb.client.model.vault.EncryptOptions in project mongo-java-driver by mongodb.

the class ClientSideEncryptionCorpusTest method testCorpus.

@Test
public void testCorpus() throws IOException, URISyntaxException {
    // Step 5: Iterate over corpus
    BsonDocument corpus = bsonDocumentFromPath("corpus.json");
    BsonDocument corpusCopied = new BsonDocument();
    for (String field : corpus.keySet()) {
        if (!corpus.get(field).isDocument()) {
            corpusCopied.append(field, corpus.get(field));
            continue;
        }
        BsonDocument fieldDocument = corpus.getDocument(field).clone();
        String kms = fieldDocument.getString("kms").getValue();
        String abbreviatedAlgorithName = fieldDocument.getString("algo").getValue();
        String method = fieldDocument.getString("method").getValue();
        String identifier = fieldDocument.getString("identifier").getValue();
        boolean allowed = fieldDocument.getBoolean("allowed").getValue();
        BsonValue value = fieldDocument.get("value");
        byte[] awsKeyId = Base64.getDecoder().decode("AWSAAAAAAAAAAAAAAAAAAA==");
        byte[] azureKeyId = Base64.getDecoder().decode("AZUREAAAAAAAAAAAAAAAAA==");
        byte[] gcpKeyId = Base64.getDecoder().decode("GCPAAAAAAAAAAAAAAAAAAA==");
        byte[] kmipKeyId = Base64.getDecoder().decode("KMIPAAAAAAAAAAAAAAAAAA==");
        byte[] localKeyId = Base64.getDecoder().decode("LOCALAAAAAAAAAAAAAAAAA==");
        if (method.equals("auto")) {
            corpusCopied.append(field, corpus.get(field));
            continue;
        }
        if (!method.equals("explicit")) {
            throw new UnsupportedOperationException("Unsupported method: " + method);
        }
        String fullAlgorithmName = "AEAD_AES_256_CBC_HMAC_SHA_512-";
        if (abbreviatedAlgorithName.equals("rand")) {
            fullAlgorithmName += "Random";
        } else if (abbreviatedAlgorithName.equals("det")) {
            fullAlgorithmName += "Deterministic";
        } else {
            throw new UnsupportedOperationException("Unsupported algorithm: " + abbreviatedAlgorithName);
        }
        EncryptOptions opts = new EncryptOptions(fullAlgorithmName);
        if (identifier.equals("id")) {
            switch(kms) {
                case "aws":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, awsKeyId));
                    break;
                case "azure":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, azureKeyId));
                    break;
                case "gcp":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, gcpKeyId));
                    break;
                case "kmip":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, kmipKeyId));
                    break;
                case "local":
                    opts.keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, localKeyId));
                    break;
                default:
                    throw new UnsupportedOperationException("Unsupported provider: " + kms);
            }
        } else if (identifier.equals("altname")) {
            opts.keyAltName(kms);
        } else {
            throw new UnsupportedOperationException("Unsupported identifier: " + identifier);
        }
        try {
            BsonValue encryptedValue = Mono.from(clientEncryption.encrypt(value, opts)).block(TIMEOUT_DURATION);
            fieldDocument.put("value", encryptedValue);
            corpusCopied.append(field, fieldDocument);
        } catch (MongoException e) {
            if (allowed) {
                throw e;
            }
            corpusCopied.append(field, fieldDocument);
        }
    }
    // Step 6: insert corpusCopied
    MongoCollection<BsonDocument> encryptedCollection = autoEncryptingClient.getDatabase("db").getCollection("coll", BsonDocument.class);
    Mono.from(encryptedCollection.insertOne(corpusCopied)).block(TIMEOUT_DURATION);
    // Step 7: check the auto decrypted document
    BsonDocument corpusDecrypted = Mono.from(encryptedCollection.find(new BsonDocument()).first()).block(TIMEOUT_DURATION);
    assertEquals(corpus, corpusDecrypted);
    // Step 8: check the document with an unencrypted client
    MongoCollection<BsonDocument> coll = client.getDatabase("db").getCollection("coll", BsonDocument.class);
    BsonDocument corpusEncryptedActual = Mono.from(coll.find(new BsonDocument()).first()).block(TIMEOUT_DURATION);
    BsonDocument corpusEncryptedExpected = bsonDocumentFromPath("corpus-encrypted.json");
    for (String field : corpusEncryptedExpected.keySet()) {
        if (field.equals("_id") || field.equals("altname_aws") || field.equals("altname_local")) {
            continue;
        }
        boolean allowed = corpusEncryptedActual.getDocument(field).getBoolean("allowed").getValue();
        String algorithm = corpusEncryptedActual.getDocument(field).getString("algo").getValue();
        BsonValue actualValue = corpusEncryptedActual.getDocument(field).get("value");
        BsonValue expectedValue = corpusEncryptedExpected.getDocument(field).get("value");
        if (algorithm.equals("det")) {
            assertEquals(actualValue, expectedValue);
        } else if (algorithm.equals("rand")) {
            if (allowed) {
                assertNotEquals(actualValue, expectedValue);
            }
        } else {
            throw new UnsupportedOperationException("Unsupported algorithm type: " + algorithm);
        }
        if (allowed) {
            BsonValue decrypted = Mono.from(clientEncryption.decrypt(actualValue.asBinary())).block(TIMEOUT_DURATION);
            BsonValue expectedDecrypted = Mono.from(clientEncryption.decrypt(expectedValue.asBinary())).block(TIMEOUT_DURATION);
            assertEquals("Values should be equal for field " + field, expectedDecrypted, decrypted);
        } else {
            assertEquals("Values should be equal for field " + field, expectedValue, actualValue);
        }
    }
}
Also used : MongoException(com.mongodb.MongoException) BsonDocument(org.bson.BsonDocument) EncryptOptions(com.mongodb.client.model.vault.EncryptOptions) BsonBinary(org.bson.BsonBinary) BsonString(org.bson.BsonString) Fixture.getMongoClientBuilderFromConnectionString(com.mongodb.reactivestreams.client.Fixture.getMongoClientBuilderFromConnectionString) BsonValue(org.bson.BsonValue) Test(org.junit.Test)

Aggregations

EncryptOptions (com.mongodb.client.model.vault.EncryptOptions)14 BsonString (org.bson.BsonString)14 BsonBinary (org.bson.BsonBinary)13 DataKeyOptions (com.mongodb.client.model.vault.DataKeyOptions)9 Document (org.bson.Document)8 Test (org.junit.Test)8 BsonDocument (org.bson.BsonDocument)7 ClientEncryption (com.mongodb.client.vault.ClientEncryption)5 HashMap (java.util.HashMap)5 ClientEncryptionSettings (com.mongodb.ClientEncryptionSettings)4 ConnectionString (com.mongodb.ConnectionString)4 MongoClientSettings (com.mongodb.MongoClientSettings)4 MongoNamespace (com.mongodb.MongoNamespace)4 IndexOptions (com.mongodb.client.model.IndexOptions)4 SecureRandom (java.security.SecureRandom)4 Map (java.util.Map)4 InsertOneResult (com.mongodb.client.result.InsertOneResult)3 OperationSubscriber (reactivestreams.helpers.SubscriberHelpers.OperationSubscriber)3 ClusterFixture.isClientSideEncryptionTest (com.mongodb.ClusterFixture.isClientSideEncryptionTest)2 MongoException (com.mongodb.MongoException)2