New feature: ca_certs support RHEL#633
Conversation
|
this is really good timing, becausei just opened https://bugs.launchpad.net/cloud-init/+bug/1901915 to add FreeBSD support, so this is fantastic groundwork! |
59fff6f to
bb55661
Compare
|
Hello! Thank you for this proposed change to cloud-init. This pull request is now marked as stale as it has not seen any activity in 14 days. If no activity occurs within the next 7 days, this pull request will automatically close. If you are waiting for code review and you are seeing this message, apologies! Please reply, tagging mitechie, and he will ensure that someone takes a look soon. (If the pull request is closed, please do feel free to reopen it if you wish to continue working on it.) |
|
@mitechie yes, this is awaiting code review and it already has someone assigned |
OddBloke
left a comment
There was a problem hiding this comment.
Hi @cawamata, thanks for taking the time to work on this and improve cloud-init! I have some comment on the code inline. Let me know if you have any questions!
I'd also like to see the testing here expanded: currently it only covers Ubuntu's behaviour in most cases, and we should at least be covering Red Hat's too. Is expanding the testing something you feel comfortable doing?
Thanks again!
| CA_CERT_FULL_PATH = os.path.join(CA_CERT_PATH, CA_CERT_FILENAME) | ||
|
|
||
| distros = ['alpine', 'debian', 'ubuntu'] | ||
| DISTRO_DEFAULT_CONFIG = { |
There was a problem hiding this comment.
There's a lot of repetition in here; perhaps it's worth having a DEFAULT_CONFIG and a DISTRO_OVERRIDES, so we only capture the Ubuntu/Debian/Alpine settings once? _distro_ca_certs_config would then look in DISTRO_OVERRIDES and return a value found in there, otherwise return DEFAULT_CONFIG.
What do you think?
There was a problem hiding this comment.
I'm not sure Ubuntu/Debian/Alpine is set as DEFAULT_CONFIG, because I don't know cloud-init's default distros..
However, if we can use I agree your proposal
There was a problem hiding this comment.
cloud-init doesn't really have default distros. All I mean here is that those three distros share a common config, so we only need to store it once; as that'll be what we use if there isn't a more specific configuration to use, it is the default configuration, by definition.
Does that make sense?
| """Construct a distro-specific ca_certs config dictionary by merging | ||
| distro specific changes into base config. |
There was a problem hiding this comment.
This docstring doesn't sound quite right: this doesn't perform any merging, and we don't have a base config.
| distro specific changes into base config. | ||
|
|
||
| @param distro: String providing the distro class name. | ||
| @returns: Dict of distro configurations for ntp clients. |
| @param certs: A list of certificate strings. | ||
| """ | ||
| distro_cfg = _distro_ca_certs_configs(distro_name) | ||
| if certs: |
There was a problem hiding this comment.
You didn't add this line, but as you're already modifying this entire function, inverting this to:
if not certs:
returnwould allow you to dedent everything else in here by one step.
There was a problem hiding this comment.
(that's one of my favourite things to do)
| 'rhel': { | ||
| 'ca_cert_path': '/usr/share/pki/ca-trust-source/', | ||
| 'ca_cert_filename': 'anchors/cloud-init-ca-certs.crt', | ||
| 'ca_cert_config': '', |
There was a problem hiding this comment.
It's preferable to use None to indicate absence of a value, rather than the empty value.
| if os.stat(distro_cfg['ca_cert_config']).st_size == 0: | ||
| # If the CA_CERT_CONFIG file is empty (i.e. all existing | ||
| # CA certs have been deleted) then simply output a single | ||
| # line with the cloud-init cert filename. | ||
| out = "%s\n" % distro_cfg['ca_cert_filename'] | ||
| else: | ||
| # Append cert filename to CA_CERT_CONFIG file. | ||
| # We have to strip the content because blank lines in the file | ||
| # causes subsequent entries to be ignored. (LP: #1077020) | ||
| orig = util.load_file(distro_cfg['ca_cert_config']) | ||
| cr_cont = '\n'.join([line for line in orig.splitlines() | ||
| if line != distro_cfg['ca_cert_filename']]) | ||
| out = "%s\n%s\n" % (cr_cont.rstrip(), | ||
| distro_cfg['ca_cert_filename']) | ||
| util.write_file(distro_cfg['ca_cert_config'], out, omode="wb") |
There was a problem hiding this comment.
This feels like it could quite naturally be refactored to a separate function; what do you think?
There was a problem hiding this comment.
current function is included add_ca_certs and update_cert_config, so I agree to separate this
| util.write_file(distro_cfg['ca_cert_config'], "", mode=0o644) | ||
|
|
||
| if distro_name != 'alpine': | ||
| if distro_name == 'debian' or distro_name == 'ubuntu': |
There was a problem hiding this comment.
| if distro_name == 'debian' or distro_name == 'ubuntu': | |
| if distro_name in ['debian', 'ubuntu']: |
reflect PR review comments
Co-authored-by: Mina Galić <me+github@igalic.co>
igalic
left a comment
There was a problem hiding this comment.
i'd like to see more explicit rhel tests
| 'ca_cert_filename': 'cloud-init-ca-certs.crt', | ||
| 'ca_cert_config': '/etc/ca-certificates.conf', | ||
| 'ca_cert_system_path': '/etc/ssl/certs/', | ||
| 'ca_cert_update_exe': 'update-ca-certificates' |
There was a problem hiding this comment.
i would call this ca_cert_update_cmd and make it an array, which is what subp expects
There was a problem hiding this comment.
I updated, please check
| """ | ||
| subp.subp(["update-ca-certificates"], capture=False) | ||
| distro_cfg = _distro_ca_certs_configs(distro_name) | ||
| subp.subp([distro_cfg['ca_cert_update_exe']], capture=False) |
There was a problem hiding this comment.
that way, we're ready for a future distro where the update command is actually a sub-command, that this function cannot possibly know about
igalic
left a comment
There was a problem hiding this comment.
this looks pretty good from my perspective
|
@OddBloke san |
|
|
||
| def update_ca_certs(): | ||
|
|
||
| def _distro_ca_certs_configs(distro): |
There was a problem hiding this comment.
A nit (so no need to address it for this to land), but distro is used elsewhere in this file to mean "a Distro instance"; using distro_name instead would avoid that.
There was a problem hiding this comment.
I updated, please check
| @param distro: String providing the distro class name. | ||
| """ | ||
| subp.subp(["update-ca-certificates"], capture=False) | ||
| distro_cfg = _distro_ca_certs_configs(distro_name) |
There was a problem hiding this comment.
We call _distro_ca_certs_config(distro_name) in many different places in this PR. Do you think it would make sense to instead call it once (in handle) and then pass the configuration dict itself around?
There was a problem hiding this comment.
Okay, to update this, I have to update test case, too.
So I will try
There was a problem hiding this comment.
I updated, please confirm
Proposed Commit Message
New feature of ca_certs, support RHEL
Test Steps
user-data: same as Ubuntu case
on RHEL Server, I confirmed the followings
trust listChecklist: