What is the recommended means to enforce strong cryptographic settings on FCOS? For example, if I want to remove weak ciphers for SSH key exchange etc do I need to faff around with defining these explicitly in fcct as drop-in type configs or is there a better way to define ‘strong’? I see in upstream Fedora there seems to be something going on with update-crypto-policies but I can’t find anything that explains the FCOS position on this - now and future? Thanks for any insights you can provide.
Hi, this is a great question. We don’t have any high level fcct “sugar” for this, though I think that’d be a good enhancement.
So today the answer is inded to use fcct/Ignition to replace /etc/crypto-policies/config
with the contents you want, and also add a systemd unit to run update-crypto-policies
.
crypto-policies
was discussed in python3 getting pulled in by crypto-policies · Issue #280 · coreos/fedora-coreos-tracker · GitHub. We currently don’t ship update-crypto-policies
as it requires Python.
It’s a pain right now, but one way to set the policy on FCOS is in your Ignition config, change the symlinks in /etc/crypto-policies/back-ends
and the contents of /etc/crypto-policies/state/current
.
We could have sugar for that, or alternatively try to rewrite update-crypto-policies
in a compiled language.
Filed Make it easier to change crypto policy · Issue #607 · coreos/fedora-coreos-tracker · GitHub about this.
Another approach I mentioned there which I’ve just tested is:
(host)$ podman run --privileged -v /etc/crypto-policies:/etc/crypto-policies -ti --rm registry.fedoraproject.org/fedora:32 /bin/bash
(cnt)$ dnf install -y crypto-policies-scripts
(cnt)$ update-crypto-policies --no-reload --set FUTURE
But see caveats in ticket.
Thanks @jlebon. Both responses were useful to me in building understanding here. I’ve gone with the fcct solution but I think this too may ultimately prove brittle subject to version changes.
The fcct snippet that worked for me for the first solution is:
# FCOS is delivered without upstream Fedora's update-crypto-policies because
# of the python dependency. So, instead we overwrite the file indicating the
# security profile to apply, and re-write all the symbolic links for current
# security settings to point to defined crypto policy, e.g. DEFAULT, FUTURE etc.
- path: /etc/crypto-policies/state/current
overwrite: true
mode: 0644
contents:
inline: {cluster_crypto_policy}
links:
- path: /etc/crypto-policies/back-ends/bind.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/bind.txt
- path: /etc/crypto-policies/back-ends/gnutls.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/gnutls.txt
- path: /etc/crypto-policies/back-ends/java.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/java.txt
- path: /etc/crypto-policies/back-ends/krb5.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/krb5.txt
- path: /etc/crypto-policies/back-ends/libreswan.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/libreswan.txt
- path: /etc/crypto-policies/back-ends/libssh.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/libssh.txt
- path: /etc/crypto-policies/back-ends/nss.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/nss.txt
- path: /etc/crypto-policies/back-ends/openssh.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/openssh.txt
- path: /etc/crypto-policies/back-ends/opensshserver.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/opensshserver.txt
- path: /etc/crypto-policies/back-ends/opensslcnf.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/opensslcnf.txt
- path: /etc/crypto-policies/back-ends/openssl.config
overwrite: true
target: /usr/share/crypto-policies/{cluster_crypto_policy}/openssl.txt
Hey @fifofonix, what version of FCOS are you using? You’re using absolute symlinks which was broken at one point and only recently fixed in testing
(not yet in stable
).
My testing was with FCOS testing stream with an fcct 1.1.0 definition. Thanks for the warning on this as re-creation of our production stacks right now (based on stable) would presumably fail - until next stable release is made.
Yep. Next stable release should be out next week. The workaround is to use relative symlinks if you need something now.
This was solved by input from @jlebon and others but I wanted to re-summarize and add a little more:
- Summary: The recommended way to modify crypto policy is to apply one of the pre-defined policy levels (e.g. NEXT, FUTURE) and if necessary apply one of the pre-defined policy modification modules to refine to your needs (e.g. NEXT:NO-SHA1). Or, if that doesn’t work define your own policy modification module and apply that (e.g. NEXT:ACME).
- Detail: To apply the crypto policy in the absence of the python scripts (see discussion) @jlebon detailed a means (with some caveats) using a privileged podman container. This can be wrapped into a oneshot systemd ignition file, referencing your policy level preference and modifications.
- Caution 1: FUTURE is probably too strict for the time being, without some fine tuning of the openssl SECLEVEL, since it will prevent auto-OS updates being applied without other modifications due to the need for all intermediate CAs to be using keys in excess of 2048 bits. NEXT on the other hand is a good move eliminating some legacy TLS protocols whilst allowing auto-OS updates by zincati/Cincinatti.
- Caution 2: If you are going to apply a policy modification, e.g. (NEXT:NO-SHA1) one of the existing ones, or your own, note that you cannot use the alternate implementation method suggested in the answers which defines links to pre-defined crypto settings. The python scripts do something else that is not encompassed by that answer when applying a modification module - a dynamic regen of a larger policy document?
- Background: Good presentation on crypto settings and illustrating how to use policy modification policies to fine tune them.
This is an example of an ignition that works although the systemd could be made a lot better I’m sure. It reboots the machine post application of policy changes without reference to other system state. It might be better with a ConditionFirstBoot if you don’t have other rebooting going on.
- path: /etc/crypto-policies/policies/modules/ACME.pmod
mode: 0644
contents:
inline: |
hash = -SHA1
sign = -RSA-PSS-SHA1 -RSA-SHA1 -ECDSA-SHA1
sha1_in_certs = 0
ssh_cipher = -AES-256-CBC -AES-128-CBC
- name: set-crypto-policy.service
enabled: true
contents: |
[Unit]
Description=Enable NEXT:ACME
# ConditionFirstBoot=true
Wants=network-online.target
[Service]
Type=oneshot
# Verify current policy state and if not NEXT:ACME make it so...
ExecStart=/bin/sh -c ' \
if [[ "$(cat /etc/crypto-policies/state/current)" != "NEXT:ACME" ]]; then \
/bin/podman run --privileged -v /etc/crypto-policies:/etc/crypto-policies -ti \
--rm registry.fedoraproject.org/fedora:32 /bin/bash -c \
"dnf install -y crypto-policies-scripts && update-crypto-policies \
--no-reload --set NEXT:ACME"; \
reboot; \
fi'
[Install]
WantedBy=multi-user.target
@dustymabe and @jlebon please let me know how we can improve upon the solution above to come up with a non-persistent SELINUX change that does not then subsequently impact upgrades.
AFAIU what you’re doing above doesn’t touch the SELinux policy. Is it possible you’re doing something else or maybe ran a one off command somewhere?
You’re right of course. This is crypto policy relate and not SELinux related. I figured out where the real SELinux was in my configuration and I’ll be documenting that in another item on this board tomorrow.
So ‘solution’ above hard codes the fedora version (my bad) and once applied effectively pins the security policy meaning it does not benefit from future system wide recommended changes. This should be easily fixable with a uname based lookup but @dustymabe or @jlebon is there a recommended systemd unit template for tasks that should be executed on FCOS major (or minor) version tick?
I don’t think we have that. I would look at VERSION_ID=34
from /etc/os-release
.
Things have moved on in Fedora land in terms of crypto policies available since this thread originated with new base policy names available as described here:
This was solved by input from @jlebon and others but I wanted to re-summarize and add a little more:
- Summary : The recommended way to modify crypto policy is to apply one of the pre-defined policy levels (e.g. FUTURE, FIPS) and if necessary apply one of the pre-defined policy modification modules to refine to your needs (e.g. FUTURE:NO-SHA1). Or, if that doesn’t work define your own policy modification module and apply that (e.g. FUTURE:ACME).
- Detail : To apply the crypto policy in the absence of the python scripts (see discussion ) @jlebon detailed a means (with some caveats) using a privileged podman container. This can be wrapped into a oneshot systemd ignition file, referencing your policy level preference and modifications.
- Caution 1 : FUTURE is probably too strict for the time being, without some fine tuning of the openssl SECLEVEL, since it will prevent auto-OS updates being applied without other modifications due to the need for all intermediate CAs to be using keys in excess of 2048 bits. NEXT on the other hand is a good move eliminating some legacy TLS protocols whilst allowing auto-OS updates by zincati/Cincinatti.
- Caution 2 : If you are going to apply a policy modification, e.g. (NEXT:NO-SHA1) one of the existing ones, or your own, note that you cannot use the alternate implementation method suggested in the answers which defines links to pre-defined crypto settings. The python scripts do something else that is not encompassed by that answer when applying a modification module - a dynamic regen of a larger policy document?
- Background : Good presentation on crypto settings and illustrating how to use policy modification policies to fine tune them.
This is an example of an ignition that works although the systemd could be made a lot better I’m sure. It re-applies base policy and applies policy modifications on the boot subsequent to any OS update initiating a further reboot.
In this iteration:
- Base policy changed from CURRENT to FUTURE (NEXT seems still to be a functional option but no longer seems documented). Applied policy modification is ACME so we pivot from CURRENT to FUTURE:ACME
- Fedora container image label required to apply policy modifications is referenced dynamically using Fedora major version number.
- Systemd unit now re-runs whenever the unit systemd-update-done is active. The goal of this is to have the unit run on the boot following a FCOS upgrade. This is required because otherwise the modified policy would be forever pinned and not benefit from evolving best standards in future OS versions.
- This seems to work but it will also trigger if for example a new package is layered via
rpm-ostree
. However, it probably needs re-working to use a ‘stamp file’ that captures the lastuname -r
for which the unit has run to make it properly transactional (I think if a reboot were triggered midway through this unit’s execution then it would not re-trigger automatically). - The given policy modification file still contains
cipher
as a policy modification although this is deprecated in fedora 35 and will need to be replaced by something likecipher@ssh
for each backend where customization is desired. I have yet to find documentation on this and am still figuring it out. - I am not at all confident on systemd units so welcome any improvement feedback.
variant: fcos
version: 1.3.0
storage:
files:
- path: /etc/crypto-policies/policies/modules/ACME.pmod
mode: 0644
contents:
inline: |
# This is an ACME extension to default NO-SHA1 mod to further remove
# the CBC tls_ciphers thereby improving SSH.
hash = -SHA1
sign = -RSA-PSS-SHA1 -RSA-SHA1 -ECDSA-SHA1
sha1_in_certs = 0
cipher = -AES-256-CBC -AES-128-CBC
#cipher@ssh = -AES-256-CBC -AES-128-CBC
#cipher@openssh-server = -AES-256-CBC -AES-128-CBC
systemd:
units:
- name: acme-set-crypto-policy.service
enabled: true
contents: |
[Unit]
Description=Enable FUTURE:ACME crypto settings
BindsTo=systemd-update-done.service
Requires=network-online.target
After=systemd-update-done.service network-online.target
[Service]
Type=oneshot
# Alternative to BindsTo+After:
# ExecCondition=/usr/bin/systemctl is-active --quiet systemd-update-done.service
ExecStartPre=/bin/sleep 10
# Alternatively:
# FEDORA_VERSION=$(cat /etc/os-release | grep VERSION_ID | cut -d\= -f2)
ExecStart=/bin/sh -c 'FEDORA_VERSION=$(uname -r | sed -r "s/^.*fc([0-9][0-9]).*/\1/"); \
if ( /bin/podman run --privileged -v /etc/crypto-policies:/etc/crypto-policies -i \
--rm registry.fedoraproject.org/fedora:$FEDORA_VERSION /bin/bash -c \
"dnf install -y crypto-policies-scripts && update-crypto-policies \
--no-reload --set FUTURE:ACME" ); then \
reboot; \
else \
exit 1; \
fi'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Comparison matrix of different crypto policies here showing clearly that FUTURE is beyond FIPS in terms of crypto policy settings. Obviously, FUTURE also more likely to cause issues, e.g. presently with layering of packages from fedora mirrors since these do not yet adhere to implied required crypto standards (experienced when layering open-vm-tools for example).