Skip to content
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

Feat[bmq, mqb]: Support TLS listeners #549

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

hallfox
Copy link
Collaborator

@hallfox hallfox commented Dec 16, 2024

Added

  • TLS configuration in broker config
  • Helper script for generating test certs and CAs
  • TLS options for NtcChannel
  • Loading certificates and authority data specified from bmqbrkrcfg.json
  • SessionOptions to bmq package for configuring client sessions
  • --tls-authority and --tls-version options to bmqtool to configure session options
  • Client sessions will now require broker TLS sessions when TLS protocol versions are specified
  • Create CertificateStore component for bmqio
  • Integration tests for TLS

Changed

  • Update ntf-core and bde dependencies

@hallfox hallfox changed the title Support TLS listeners Feat[bmq, mqb]: Support TLS listeners Dec 16, 2024
@hallfox hallfox force-pushed the tls-poc branch 5 times, most recently from 93f478c to a1e957d Compare December 17, 2024 21:15
Copy link
Contributor

@chrisbeard chrisbeard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very quick pass on the draft

Comment on lines 11 to 12
"loggingVerbosity": "TRACE",
"consoleSeverityThreshold": "TRACE",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, seems like a leftover from local testing

ntca::EncryptionClientOptions encryptionClientOptions;
// Set the minimum version to TLS 1.3
encryptionClientOptions.setMinMethod(ntca::EncryptionMethod::e_TLS_V1_3);
encryptionClientOptions.setMaxMethod(ntca::EncryptionMethod::e_TLS_V1_3);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious to see what others think here. From the ntc docs, it looks like we could use e_DEFAULT here. The client can then use v1.3 up to ntc's max supported version without needing to make code changes here (when 1.4 eventually lands)?

struct EncryptionMethod {
  public:
    /// Enumerate the methods of encryption.
    enum Value {
        /// When specified as a minimum version, the minimum version is
        /// interpreted as the minimum version suggested by the current
        /// standards of cryptography. When specified as a maximum version, the
        /// maximum version is interpreted as the maximum version supported by
        /// the implementation.
        e_DEFAULT,
        ...

@hallfox hallfox force-pushed the tls-poc branch 2 times, most recently from a5ff6ec to 7b352d4 Compare January 10, 2025 23:50
Added
=====

- TLS configuration in broker config
- Helper script for generating test certs and CAs
- TLS options for NtcChannel
- Loading certificates and authority data specified from bmqbrkrcfg.json
- SessionOptions to bmq package for configuring client sessions
- --tls-authority and --tls-version options to bmqtool to configure
  session options
- Client sessions will now require broker TLS sessions when TLS protocol
  versions are specified
- Create CertificateStore component for bmqio
- Integration tests for TLS

Changed
=======

- Update ntf-core and bde dependencies

Signed-off-by: Taylor Foxhall <tfoxhall@bloomberg.net>

Signed-off-by: Evgeny Malygin <emalygin@bloomberg.net>
@dorjesinpo dorjesinpo self-assigned this Feb 20, 2025
@dorjesinpo dorjesinpo self-requested a review February 20, 2025 16:12
@@ -272,6 +272,8 @@ class Parameters {
// A name of a property to put auto-incremented values
// in batch-posting mode.

bsl::string d_certificateAuthority;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's initialize this field in this constructor:

Parameters::Parameters(bslma::Allocator* allocator)

And add it to this printer:

Parameters::print(bsl::ostream& stream, int level, int spacesPerLevel) const

statContextCreator,
const bmqp_ctrlmsg::NegotiationMessage& negotiationMessage,
BlobSpPool* blobSpPool,
bslma::Allocator* allocator)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The args list for this method can be rearranged so the non const ptrs (except allocator) go first. Can do it later

void Application::ChannelFactoryPipeline::stop()
{
d_reconnectingChannelFactory.stop();
d_channelFactory.stop();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    bmqio::NtcChannelFactory          d_channelFactory;
    bmqio::ResolvingChannelFactory    d_resolvingChannelFactory;
    bmqio::ReconnectingChannelFactory d_reconnectingChannelFactory;
    bmqio::StatChannelFactory         d_statChannelFactory;
    NegotiatedChannelFactory          d_negotiatedChannelFactory;

There are 5 different factories stored as fields, should all of them be stopped here? Or either there should be a comment that some of these factories are stopped from other factories that hold them.

return bmqt::GenericResult::e_SUCCESS;
}

void Application::ChannelFactoryPipeline::stop()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we miss calling stop in destructor, or either checking that everything was stopped there. There are a lot of new code and classes in this PR, so it's worth adding more state conditions checks

@@ -88,6 +88,59 @@ class Application {
typedef bslma::ManagedPtr<bmqio::ChannelFactory::OpHandle>
ChannelFactoryOpHandleMp;

class ChannelFactoryPipeline : public bmqio::ChannelFactory {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bmqimp::Application::ChannelFactoryPipeline and mqbnet::TCPSessionFactory::ChannelFactoryPipeline have very similar interfaces. There are some differences though:

  • bmqimp::Application::ChannelFactoryPipeline: extra field NegotiatedChannelFactory d_negotiatedChannelFactory
  • fields are stored as managed pointers or direct values

Is it possible to unify interfaces, make a new component bmqio_channelfactorypipeline and reuse it from both places?

Comment on lines +98 to +99
bmqvt::ValueOrError<Certificate, Error>
loadCertificateFromPath(const bsl::string& path) BSLS_KEYWORD_OVERRIDE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value type here makes us use Error that is inherited from ntsa::Error, so we expose ntf symbols and header.

There are different ways of returning results, in this header we also have this:

    int loadCertificateAuthority(CertificateLoader& loader,
                                 const bsl::string& caPath);

We can return Certificate and/or Error via pointer args. We can also return (possibly null) shared pointer to Certificate as a return value and pass output stream to log any errors, to hide ntsa::Error

const ntca::UpgradeEvent& upgradeEvent,
const ntci::UpgradeFunction& cb)
{
BSLS_ASSERT(cb);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An interesting question if we should check this.
If cb is empty, an exception will be thrown when we try to call it a few lines below anyway. We check the same thing twice.
However, we don't do this often, it's not the data path.

const ntci::EncryptionClient& encryptionClient() const;

/// @brief Access this factory's upgrade options.
const ntca::UpgradeOptions& upgradeOptions() const;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These added accessors are not used.
If we don't plan to use them, we should probably remove them to simplify the code base.

void Tester::setEncryptionAuthority()
{
if (d_authorityCertificate && d_authorityPrivateKey) {
// Authority root has already been initialized, no need to set it again
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also fail the test here and in other set methods in this file. If we try to set something twice it's a problem with a test design probably

// Shorten the timeout interval
ntca::UpgradeOptions upgradeOptions;
bsls::TimeInterval deadline = bdlt::CurrentTime::now();
// 5ms doesn't seem to interfere with the success test case, so this
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we set a bigger timeout in case we run on a slower host?

@678098
Copy link
Collaborator

678098 commented Mar 6, 2025

@hallfox I have applied my fixes in this PR:
hallfox#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants