-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CSHARP-6005: CSFLE/QE support for HTTP Proxies #2077
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /* Copyright 2019-present MongoDB Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| using System.IO; | ||
| using System.Net; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using MongoDB.Driver.Core.Connections; | ||
| using MongoDB.Driver.Core.Misc; | ||
|
|
||
| namespace MongoDB.Driver.Encryption; | ||
|
|
||
| internal sealed class KmsConnectorStreamFactory : IStreamFactory | ||
| { | ||
| private readonly IKmsConnector _kmsConnector; | ||
|
|
||
| public KmsConnectorStreamFactory(IKmsConnector kmsConnector) | ||
| { | ||
| _kmsConnector = Ensure.IsNotNull(kmsConnector, nameof(kmsConnector)); | ||
| } | ||
|
|
||
| public Stream CreateStream(EndPoint endPoint, CancellationToken cancellationToken) | ||
| { | ||
| var (host, port) = GetHostAndPort(endPoint); | ||
| var stream = _kmsConnector.Connect(host, port, cancellationToken); | ||
| return Ensure.IsNotNull(stream, $"{nameof(IKmsConnector)}.{nameof(IKmsConnector.Connect)}"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: Consider a clearer message, like "connector returned null" or similar.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| } | ||
|
|
||
| public async Task<Stream> CreateStreamAsync(EndPoint endPoint, CancellationToken cancellationToken) | ||
| { | ||
| var (host, port) = GetHostAndPort(endPoint); | ||
| var stream = await _kmsConnector.ConnectAsync(host, port, cancellationToken).ConfigureAwait(false); | ||
| return Ensure.IsNotNull(stream, $"{nameof(IKmsConnector)}.{nameof(IKmsConnector.ConnectAsync)}"); | ||
| } | ||
|
|
||
| private static (string Host, int Port) GetHostAndPort(EndPoint endPoint) | ||
| { | ||
| var dnsEndPoint = (DnsEndPoint)endPoint; | ||
| return (dnsEndPoint.Host, dnsEndPoint.Port); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,7 @@ public sealed class AutoEncryptionOptions | |
| private TimeSpan? _keyExpiration; | ||
| private readonly IReadOnlyDictionary<string, BsonDocument> _encryptedFieldsMap; | ||
| private readonly IReadOnlyDictionary<string, object> _extraOptions; | ||
| private readonly IKmsConnector _kmsConnector; | ||
| private readonly IMongoClient _keyVaultClient; | ||
| private readonly CollectionNamespace _keyVaultNamespace; | ||
| private readonly IReadOnlyDictionary<string, IReadOnlyDictionary<string, object>> _kmsProviders; | ||
|
|
@@ -57,6 +58,7 @@ public sealed class AutoEncryptionOptions | |
| /// <param name="tlsOptions">The tls options.</param> | ||
| /// <param name="encryptedFieldsMap">The encryptedFields map.</param> | ||
| /// <param name="bypassQueryAnalysis">The bypass query analysis flag.</param> | ||
| /// <param name="kmsConnector">The KMS connector used to open connections to KMS hosts.</param> | ||
| public AutoEncryptionOptions( | ||
| CollectionNamespace keyVaultNamespace, | ||
| IReadOnlyDictionary<string, IReadOnlyDictionary<string, object>> kmsProviders, | ||
|
|
@@ -66,8 +68,9 @@ public AutoEncryptionOptions( | |
| Optional<IReadOnlyDictionary<string, BsonDocument>> schemaMap = default, | ||
| Optional<IReadOnlyDictionary<string, SslSettings>> tlsOptions = default, | ||
| Optional<IReadOnlyDictionary<string, BsonDocument>> encryptedFieldsMap = default, | ||
| Optional<bool?> bypassQueryAnalysis = default) | ||
| : this(keyVaultNamespace, kmsProviders, bypassAutoEncryption, extraOptions, keyVaultClient, schemaMap, tlsOptions, encryptedFieldsMap, bypassQueryAnalysis, keyExpiration: null) | ||
| Optional<bool?> bypassQueryAnalysis = default, | ||
| Optional<IKmsConnector> kmsConnector = default) | ||
| : this(keyVaultNamespace, kmsProviders, bypassAutoEncryption, extraOptions, keyVaultClient, schemaMap, tlsOptions, encryptedFieldsMap, bypassQueryAnalysis, kmsConnector, keyExpiration: null) | ||
|
adelinowona marked this conversation as resolved.
|
||
| { | ||
| } | ||
|
|
||
|
|
@@ -81,6 +84,7 @@ private AutoEncryptionOptions( | |
| Optional<IReadOnlyDictionary<string, SslSettings>> tlsOptions, | ||
| Optional<IReadOnlyDictionary<string, BsonDocument>> encryptedFieldsMap, | ||
| Optional<bool?> bypassQueryAnalysis, | ||
| Optional<IKmsConnector> kmsConnector, | ||
| Optional<TimeSpan?> keyExpiration) | ||
| { | ||
| _keyVaultNamespace = Ensure.IsNotNull(keyVaultNamespace, nameof(keyVaultNamespace)); | ||
|
|
@@ -89,6 +93,7 @@ private AutoEncryptionOptions( | |
| _bypassQueryAnalysis = bypassQueryAnalysis.WithDefault(null); | ||
| _keyExpiration = keyExpiration.WithDefault(null); | ||
| _extraOptions = extraOptions.WithDefault(null); | ||
| _kmsConnector = kmsConnector.WithDefault(null); | ||
| _keyVaultClient = keyVaultClient.WithDefault(null); | ||
| _schemaMap = schemaMap.WithDefault(null); | ||
| _tlsOptions = tlsOptions.WithDefault(new Dictionary<string, SslSettings>()); | ||
|
|
@@ -137,6 +142,14 @@ private AutoEncryptionOptions( | |
| /// </remarks> | ||
| public IReadOnlyDictionary<string, object> ExtraOptions => _extraOptions; | ||
|
|
||
| /// <summary> | ||
| /// Gets the KMS connector used to open connections to KMS hosts. | ||
| /// </summary> | ||
| /// <value> | ||
| /// The KMS connector to connect directly to KMS hosts. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think technically it's not "directly to KMS hosts"?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
| /// </value> | ||
| public IKmsConnector KmsConnector => _kmsConnector; | ||
|
|
||
| /// <summary> | ||
| /// Gets the key vault client. | ||
| /// </summary> | ||
|
|
@@ -199,6 +212,7 @@ public void SetKeyExpiration(TimeSpan? keyExpiration) | |
| /// <param name="schemaMap">The schema map.</param> | ||
| /// <param name="tlsOptions">The tls options.</param> | ||
| /// <param name="encryptedFieldsMap">The encryptedFields map.</param> | ||
| /// <param name="kmsConnector">The KMS connector used to open connections to KMS hosts.</param> | ||
| /// <returns>A new instance of <see cref="AutoEncryptionOptions"/>.</returns> | ||
| public AutoEncryptionOptions With( | ||
| Optional<CollectionNamespace> keyVaultNamespace = default, | ||
|
|
@@ -209,7 +223,8 @@ public AutoEncryptionOptions With( | |
| Optional<IMongoClient> keyVaultClient = default, | ||
| Optional<IReadOnlyDictionary<string, BsonDocument>> schemaMap = default, | ||
| Optional<IReadOnlyDictionary<string, SslSettings>> tlsOptions = default, | ||
| Optional<IReadOnlyDictionary<string, BsonDocument>> encryptedFieldsMap = default) | ||
| Optional<IReadOnlyDictionary<string, BsonDocument>> encryptedFieldsMap = default, | ||
| Optional<IKmsConnector> kmsConnector = default) | ||
| { | ||
| return new AutoEncryptionOptions( | ||
| keyVaultNamespace.WithDefault(_keyVaultNamespace), | ||
|
|
@@ -221,6 +236,7 @@ public AutoEncryptionOptions With( | |
| Optional.Create(tlsOptions.WithDefault(_tlsOptions)), | ||
| Optional.Create(encryptedFieldsMap.WithDefault(_encryptedFieldsMap)), | ||
| Optional.Create(bypassQueryAnalysis.WithDefault(_bypassQueryAnalysis)), | ||
| Optional.Create(kmsConnector.WithDefault(_kmsConnector)), | ||
| _keyExpiration); | ||
| } | ||
|
|
||
|
|
@@ -235,6 +251,7 @@ public override bool Equals(object obj) | |
| _bypassQueryAnalysis == rhs._bypassQueryAnalysis && | ||
| _keyExpiration == rhs._keyExpiration && | ||
| ExtraOptionsEquals(_extraOptions, rhs._extraOptions) && | ||
| object.ReferenceEquals(_kmsConnector, rhs._kmsConnector) && | ||
| object.ReferenceEquals(_keyVaultClient, rhs._keyVaultClient) && | ||
| _keyVaultNamespace.Equals(rhs._keyVaultNamespace) && | ||
| KmsProvidersEqualityHelper.Equals(_kmsProviders, rhs._kmsProviders) && | ||
|
|
@@ -251,6 +268,7 @@ public override int GetHashCode() | |
| .Hash(_bypassQueryAnalysis) | ||
| .Hash(_keyExpiration) | ||
| .HashElements(_extraOptions) | ||
| .Hash(_kmsConnector) | ||
| .Hash(_keyVaultClient) | ||
| .Hash(_keyVaultNamespace) | ||
| .HashElements(_kmsProviders) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /* Copyright 2019-present MongoDB Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| using System.IO; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace MongoDB.Driver.Encryption; | ||
|
|
||
| /// <summary> | ||
| /// Opens the transport connection used to reach a KMS host. When supplied via | ||
| /// ClientEncryptionOptions or <see cref="AutoEncryptionOptions"/>, the driver | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ClientEncryptionOptions ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ClientEncryptionOptions type lives in the encryption package which isn't referenced by the driver package so the see cref won't resolve. I am assuming that's your question here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I meant <c>ClientEncryptionOptions <c> |
||
| /// invokes this instead of opening a direct TCP connection to the KMS host, then wraps the | ||
| /// returned stream in TLS using the KMS provider's configured TLS options. | ||
| /// The primary use case is routing KMS traffic through an HTTP proxy via HTTPS CONNECT. | ||
| /// </summary> | ||
| public interface IKmsConnector | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this new abstraction?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussed offline but I added some reasoning in the PR description. |
||
| { | ||
| /// <summary> | ||
| /// Opens a connection to the specified KMS host. | ||
| /// </summary> | ||
| /// <param name="host">The KMS hostname (for example, <c>kms.us-east-1.amazonaws.com</c>).</param> | ||
| /// <param name="port">The KMS port.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A stream connected to the KMS host. The driver wraps this stream in TLS.</returns> | ||
| Stream Connect(string host, int port, CancellationToken cancellationToken); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we use Endpoint instead of host and port?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussed offline as well but for visibility: |
||
|
|
||
| /// <summary> | ||
| /// Opens a connection to the specified KMS host. | ||
| /// </summary> | ||
| /// <param name="host">The KMS hostname (for example, <c>kms.us-east-1.amazonaws.com</c>).</param> | ||
| /// <param name="port">The KMS port.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A stream connected to the KMS host. The driver wraps this stream in TLS.</returns> | ||
| Task<Stream> ConnectAsync(string host, int port, CancellationToken cancellationToken); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adelinowona I guess we'll address this during backporting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep