-
Notifications
You must be signed in to change notification settings - Fork 130
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
[WIP] Refs #34239 - [rex_ssh] Install mosquitto with 'pull-mqtt' mode #726
Conversation
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.
Something I never got clarity on is whether MQTT mode still supports SSH mode or if you really need to choose between the two.
metadata.json
Outdated
{ | ||
"name": "puppet/mosquitto", | ||
"version_requirement": ">= 1.0.1 < 2.0.0" | ||
}, |
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.
I wonder if this should be a hard dependency or rather a soft one. It's really an edge case so most users won't need it.
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.
If it's a soft dependency, it would need to be included explicitly in the installer Puppetfile?
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.
With the soft dependency approach (what I have now implemented) what is the proper method to test?
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.
add it to .fixtures.yml
@@ -7,3 +7,7 @@ | |||
|
|||
# Whether to run remote execution jobs asynchronously | |||
:mode: <%= scope.lookupvar("::foreman_proxy::plugin::remote_execution::ssh::mode") %> | |||
<% if scope.lookupvar("::foreman_proxy::plugin::remote_execution::ssh::mode") == 'pull-mqtt' -%> | |||
:mqtt_broker: localhost | |||
:mqtt_port: 1883 |
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.
It would be nice if this port was somehow extracted from the mosquitto config.
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.
Will add the additional params necessary to make that happen
@@ -7,3 +7,7 @@ | |||
|
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.
Are the options above this (like ssh_identify_key_file
and kerberos_auth
still relevant in mqtt mode?
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.
@adamruzicka Is this something that you can answer for us? See the question from above comment as well:
Something I never got clarity on is whether MQTT mode still supports SSH mode or if you really need to choose between the two.
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.
kerberos_auth
is only applicable if one of the ssh modes is used.
ssh_identify_key_file
is only applicable for ssh modes and ansible. This is probably something that should be looked into as well
smart_proxy_remote_execution_ssh
validates that a private key really exists at the location specified by ssh_identity_key_file
, regardless of the selected mode[1].
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.
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.
Hmm, now that I'm thinking about it again, the ssh key is used for web console integration no matter what mode is used. So maybe always managing the key isn't a bad idea?
They are mutually exclusive, you really need to choose between the two, or at least as long as |
It sounds to me like it should have been implemented as:
That would have been in line with how the Smart Proxy implements abstraction. The However, the Ansible part complicates things. |
IIRC the plan was to rename "SSH" provider in foreman to "Script" and then having ssh or mqtt as a different transport between the proxy and the target hosts. Once it goes underway, we could rename
And salt too |
7435214
to
3a6116e
Compare
|
||
if $mode == 'pull-mqtt' { | ||
class { 'mosquitto': | ||
package_name => 'mosquitto', |
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.
what's the reason for overriding the package name here?
Is there a way (in Kafo?) to make Right now, the help ends up being:
Which makes it hard for the user to discover they need to pass (obviously, totally unrelated to the actual change in this PR, but something that jumped at me) |
Couple of architectural questions:
|
This will need updating as clients need to connect to the mosquitto instance.
@adamruzicka Can you speak to this? Is auth a TODO for talking to mosquitto from REX plugin?
I think you are describing the Qpid model which we were not intending to do with the pull provider. Rather, Foreman tells a Foreman Proxy that there is a job for a host, and the smart-proxy then relays that to the mosquitto running on the proxy itself. |
Pretty much yes. What I didn't know back then, and still I'm not sure, is whether we can just reuse the set of certs the proxy already has or if there will have to be another set. Here I'm assuming the certs proxy already has and consumer certs clients use are issued by different CAs which might pose a problem? |
In the Katello scenario, all involved parties have certs issued by the Katello CA. |
A brief recap how the auth was planned: Mosquitto should use ACLs to grant access to topics based on a CN present in client's (even a smart-proxy is a client in this context) cert. Hosts only need read access to their own topics, smart-proxy needs to be able to write to all of the per-host topics. Per @jlsherrill 's comment this should work, just the topic names will be slightly different. In the Katello and Foreman with puppet scenarios dealing with certs should be pretty straight forward. In the dragon scenario, both mosquitto and yggdrasil can be configured to trust any cert signed by one of many configured CAs. While it may need special handling, hopefully there won't be that many dragons. It would be great if in this PR we could:
In the meantime I'll take a stab at making sp-rex reuse smart-proxy's certs when connecting to mosquitto. |
subscribing with CLI (on client): # mosquitto_sub --cafile /etc/rhsm/ca/katello-server-ca.pem --cert /etc/pki/consumer/cert.pem --key /etc/pki/consumer/key.pem --host centos8-stream-katello-nightly.tanso.example.com --port 1883 -t THE_TOPIC publishing with CLI (on server): # mosquitto_pub -t THE_TOPIC -m THE_MESSAGE --cafile /etc/foreman-proxy/foreman_ssl_ca.pem --key /etc/foreman-proxy/foreman_ssl_key.pem --cert /etc/foreman-proxy/foreman_ssl_cert.pem -h $HOSTNAME -p 1883 publishing with proxy (on server): MQTT::Client.connect(:host => settings.mqtt_broker, :port => settings.mqtt_port, :ssl => true, :cert_file => '/etc/foreman-proxy/foreman_ssl_cert.pem', :key_file => '/etc/foreman-proxy/foreman_ssl_key.pem', :ca_file => '/etc/foreman-proxy/foreman_ssl_ca.pem') do |c|
c.publish(mqtt_topic, JSON.dump(payload), false, 1)
end test REX with: hammer job-invocation create --job-template 'Run Command - SSH Default' --inputs 'command=uptime' --search-query "name = centos8-stream.tanso.example.com" Edit: this seems to work now, ACLs are also working properly |
Nice walk through of steps and testing! If you have your setup still, do you think you could try out the dragon scenario? aka custom certificates |
3a6116e
to
56632f1
Compare
It's a simple Katello without Puppet setup, I guess I could add Puppet to the mix and add another client. |
The dragons ate my lunch! I could get mosquitto to offer both certs with the following config:
Note: it didn't like me to point at the same Note: I tried just listing both CAs in however REX didn't work in the end, as even with the Katello CA in the trust store, yggd fails to download the script:
Probably because AUTH against the proxy on 9090 also needs to happen with the Katello cert… |
How'd you do this? by setting multiple CA files in yggdrasil config or another method? |
Exactly, I added both files to the Yggdrasil config |
Just for completeness, for the dragon scenario, to connect to the Katello CA signed Mosquitto with a Puppet CA signed cert (port 1883 above), you need the following # yggdrasil global configuration settings written by katello-pull-transport-migrate
broker = ["mqtts://centos8-stream-katello-nightly.tanso.example.com:1883"]
cert-file = "/etc/puppetlabs/puppet/ssl/certs/centos7.tanso.example.com.pem"
key-file = "/etc/puppetlabs/puppet/ssl/private_keys/centos7.tanso.example.com.pem"
ca-root = ["/etc/puppetlabs/puppet/ssl/certs/ca.pem", "/etc/pki/ca-trust/source/anchors/katello-server-ca.crt"]
log-level = "debug" |
I've ran into this in the past. We sort of have this in the So it would be a matter of enhancing the help builder to describe the data type. The downside is that it may explode the size when it starts to describe complex types as well (think the regex for paths or hostnames/IPs). That's what I ran into the last time I looked at it. |
The dragon scenario I was thinking of and tested was (and seemed to work ok with a few tweaks mentioned below): Generate custom certificates (using theforeman/forklift#1481):
Now update foreman with katello install with custom certificates:
Now smart-proxy is running with the custom certificates as it's server certificates. Add back the following config and restart mosquitto:
On the client, my yggdrasil is configured as:
I also had to configure the smart-proxy with a combined CA certificate to get this work (more to come on this fun finding). |
We will need to deploy some dedicated certificates for mosquitto over in puppet-certs. I am thinking we deploy to: /etc/mosquitto/ssl And then we have two options for configuration:
|
There is a lot of great discussion here which, while I hate to lose, I have taken over this PR with #737 |
Opening this work in progress for feedback. This requires, at a minimum, tests as well as support for certificate authentication.