Skip to content

Commit ff0274a

Browse files
committed
feat(mongodb): add version tracking modes
Add version, patch-drift, and patch-status modes to monitor MongoDB patch compliance and expose them through database::mongodb::plugin. Signed-off-by: tpaskap <tpaskap@users.noreply.github.com>
1 parent e449775 commit ff0274a

5 files changed

Lines changed: 1258 additions & 9 deletions

File tree

src/database/mongodb/custom/driver.pm

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ sub new {
4949
'protocol:s' => { name => 'protocol' },
5050
'username:s' => { name => 'username' },
5151
'password:s' => { name => 'password' },
52+
'auth-source:s' => { name => 'auth_source' },
53+
'replica-set:s' => { name => 'replica_set' },
5254
'timeout:s' => { name => 'timeout' },
5355
'ssl-opt:s@' => { name => 'ssl_opt' },
5456
'no-ssl' => { name => 'no_ssl' }
@@ -79,6 +81,8 @@ sub check_options {
7981
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10;
8082
$self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : '';
8183
$self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : '';
84+
$self->{auth_source} = (defined($self->{option_results}->{auth_source})) ? $self->{option_results}->{auth_source} : '';
85+
$self->{replica_set} = (defined($self->{option_results}->{replica_set})) ? $self->{option_results}->{replica_set} : '';
8286
$self->{no_ssl} = (defined($self->{option_results}->{no_ssl})) ? 1 : 0;
8387

8488
if ($self->{hostname} eq '') {
@@ -106,25 +110,58 @@ sub get_port {
106110
return $self->{port};
107111
}
108112

109-
sub connect {
113+
sub build_uri {
110114
my ($self, %options) = @_;
111115

112-
my $uri = URI::Encode->new({encode_reserved => 1});
113-
my $encoded_username = $uri->encode($self->{username});
114-
my $encoded_password = $uri->encode($self->{password});
116+
my $encoder = URI::Encode->new({encode_reserved => 1});
117+
my $encoded_username = $encoder->encode($self->{username});
118+
my $encoded_password = $encoder->encode($self->{password});
119+
120+
my $host = defined($options{host}) && $options{host} ne '' ? $options{host} : $self->{hostname};
121+
my $port = defined($options{port}) ? $options{port} : $self->{port};
115122

116-
$uri = $self->{protocol} . '://';
123+
my $uri = $self->{protocol} . '://';
117124
$uri .= $encoded_username . ':' . $encoded_password . '@' if ($encoded_username ne '' && $encoded_password ne '');
118-
$uri .= $self->{hostname} if ($self->{hostname} ne '');
119-
$uri .= ':' . $self->{port} if ($self->{port} ne '' && $self->{protocol} ne 'mongodb+srv');
125+
$uri .= $host if ($host ne '');
126+
$uri .= ':' . $port if ($port ne '' && $host !~ /:\d+$/ && $self->{protocol} ne 'mongodb+srv');
120127

121-
$self->{output}->output_add(long_msg => 'Connection URI: ' . $uri, debug => 1);
128+
my @params = ();
129+
push @params, 'authSource=' . $encoder->encode($self->{auth_source}) if ($self->{auth_source} ne '');
130+
push @params, 'replicaSet=' . $encoder->encode($self->{replica_set}) if ($self->{replica_set} ne '');
131+
# MongoDB URI parser requires a '/' between the host list and the
132+
# query string, even when no default database is specified.
133+
$uri .= '/?' . join('&', @params) if (scalar(@params) > 0);
134+
135+
return $uri;
136+
}
137+
138+
sub redact_uri {
139+
my ($self, $uri) = @_;
140+
141+
# Hide the password between ':' and '@' in 'scheme://user:password@host...'
142+
# so that --debug never leaks credentials.
143+
$uri =~ s{(://[^:/@]+):[^@]+@}{$1:***\@};
144+
return $uri;
145+
}
146+
147+
sub build_mongodb_options {
148+
my ($self, %options) = @_;
122149

123150
my %mongodb_options = ();
124151
if ($self->{no_ssl} == 0) {
125152
$mongodb_options{ssl} = (defined($self->{ssl_opts}) && scalar(keys %{$self->{ssl_opts}}) > 0) ? $self->{ssl_opts} : 1;
126153
}
127154

155+
return %mongodb_options;
156+
}
157+
158+
sub connect {
159+
my ($self, %options) = @_;
160+
161+
my $uri = $self->build_uri();
162+
$self->{output}->output_add(long_msg => 'Connection URI: ' . $self->redact_uri($uri), debug => 1);
163+
164+
my %mongodb_options = $self->build_mongodb_options();
128165
$self->{client} = MongoDB::MongoClient->new(host => $uri, %mongodb_options);
129166
$self->{client}->connect();
130167

@@ -161,6 +198,20 @@ sub run_command {
161198
return $db->run_command($options{command});
162199
}
163200

201+
sub run_command_on_host {
202+
my ($self, %options) = @_;
203+
204+
my $uri = $self->build_uri(host => $options{host}, port => $options{port});
205+
$self->{output}->output_add(long_msg => 'Connection URI: ' . $self->redact_uri($uri), debug => 1);
206+
207+
my %mongodb_options = $self->build_mongodb_options();
208+
my $client = MongoDB::MongoClient->new(host => $uri, %mongodb_options);
209+
$client->connect();
210+
211+
my $db = $client->get_database($options{database});
212+
return $db->run_command($options{command});
213+
}
214+
164215
sub list_databases {
165216
my ($self, %options) = @_;
166217

@@ -221,6 +272,14 @@ MongoDB username.
221272
222273
MongoDB password.
223274
275+
=item B<--auth-source>
276+
277+
Authentication database (authSource connection string option).
278+
279+
=item B<--replica-set>
280+
281+
Replica set name (replicaSet connection string option).
282+
224283
=item B<--timeout>
225284
226285
Set timeout in seconds (default: 10).

0 commit comments

Comments
 (0)