-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
RHEL 10 FIPS adjustments #21264
RHEL 10 FIPS adjustments #21264
Changes from all commits
24b5660
90becdd
8dca495
dae0b2f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ | |
*/ | ||
|
||
import cockpit from "cockpit"; | ||
import React, { useState, useEffect } from 'react'; | ||
import React, { useState } from 'react'; | ||
import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js"; | ||
import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js"; | ||
import { Modal } from "@patternfly/react-core/dist/esm/components/Modal/index.js"; | ||
|
@@ -29,6 +29,7 @@ import { ModalError } from 'cockpit-components-inline-notification.jsx'; | |
import { PrivilegedButton } from "cockpit-components-privileged.jsx"; | ||
import { ProfilesMenuDialogBody } from "./profiles-menu-dialog-body.jsx"; | ||
import { useDialogs } from "dialogs.jsx"; | ||
import { useInit } from "hooks"; | ||
|
||
import "./cryptoPolicies.scss"; | ||
|
||
|
@@ -37,63 +38,87 @@ const _ = cockpit.gettext; | |
const displayProfileText = profile => profile === "DEFAULT" ? _("Default") : profile; | ||
const isInconsistentPolicy = (policy, fipsEnabled) => policy === "FIPS" !== fipsEnabled; | ||
|
||
const getFipsConfigurable = () => cockpit.spawn(["/bin/sh", "-c", "command -v fips-mode-setup"], { error: "ignore" }) | ||
.then(() => true) | ||
.catch(() => false); | ||
|
||
export const CryptoPolicyRow = () => { | ||
const Dialogs = useDialogs(); | ||
const [currentCryptoPolicy, setCurrentCryptoPolicy] = useState(null); | ||
const [fipsEnabled, setFipsEnabled] = useState(null); | ||
const [fipsConfigurable, setFipsConfigurable] = useState(null); | ||
const [shaSubPolicyAvailable, setShaSubPolicyAvailable] = useState(null); | ||
|
||
useEffect(() => { | ||
useInit(() => { | ||
cockpit.file("/proc/sys/crypto/fips_enabled").read() | ||
.then(content => setFipsEnabled(content ? content.trim() === "1" : false)); | ||
cockpit.file("/etc/crypto-policies/state/current") | ||
.watch(content => setCurrentCryptoPolicy(content ? content.trim() : null)); | ||
getFipsConfigurable().then(v => setFipsConfigurable(v)); | ||
cockpit.file("/etc/crypto-policies/config") | ||
.watch(async contents => { | ||
// Ask crypto-policies to get correct FIPS state, as that dominates the configured policy | ||
try { | ||
setCurrentCryptoPolicy((await cockpit.spawn(["update-crypto-policies", "--show"])).trim()); | ||
} catch (error) { | ||
console.warn("Failed to get current crypto policy:", error.toString(), | ||
"; falling back to /etc/crypto-policies/config"); | ||
setCurrentCryptoPolicy(contents.trim()); | ||
} | ||
}); | ||
// RHEL-8-8 has no SHA1 subpolicy | ||
cockpit.file("/usr/share/crypto-policies/policies/modules/SHA1.pmod").read() | ||
.then(content => setShaSubPolicyAvailable(content ? content.trim() : false)); | ||
}, []); | ||
}); | ||
|
||
if (!currentCryptoPolicy) { | ||
if (currentCryptoPolicy === null || fipsEnabled === null || fipsConfigurable === null) | ||
return null; | ||
} | ||
|
||
const policyRender = (currentCryptoPolicy.startsWith("FIPS") && !fipsConfigurable) | ||
/* read-only mode; can't switch away from FIPS without fips-mode-setup */ | ||
? <span id="crypto-policy-current">{displayProfileText(currentCryptoPolicy)}</span> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This added line is not executed by any test. |
||
: <PrivilegedButton variant="link" buttonId="crypto-policy-button" tooltipId="tip-crypto-policy" | ||
excuse={ _("The user $0 is not permitted to change cryptographic policies") } | ||
onClick={() => Dialogs.show(<CryptoPolicyDialog | ||
currentCryptoPolicy={currentCryptoPolicy} | ||
setCurrentCryptoPolicy={setCurrentCryptoPolicy} | ||
fipsEnabled={fipsEnabled} | ||
fipsConfigurable={fipsConfigurable} | ||
shaSubPolicyAvailable={shaSubPolicyAvailable} />)}> | ||
{displayProfileText(currentCryptoPolicy)} | ||
</PrivilegedButton>; | ||
|
||
return ( | ||
<tr className="pf-v5-c-table__tr"> | ||
<th className="pf-v5-c-table__th" scope="row">{_("Cryptographic policy")}</th> | ||
<td className="pf-v5-c-table__td"> | ||
<PrivilegedButton variant="link" buttonId="crypto-policy-button" tooltipId="tip-crypto-policy" | ||
excuse={ _("The user $0 is not permitted to change cryptographic policies") } | ||
onClick={() => Dialogs.show(<CryptoPolicyDialog | ||
currentCryptoPolicy={currentCryptoPolicy} | ||
setCurrentCryptoPolicy={setCurrentCryptoPolicy} | ||
fipsEnabled={fipsEnabled} | ||
shaSubPolicyAvailable={shaSubPolicyAvailable} />)}> | ||
{displayProfileText(currentCryptoPolicy)} | ||
</PrivilegedButton> | ||
</td> | ||
<td className="pf-v5-c-table__td">{policyRender}</td> | ||
</tr> | ||
); | ||
}; | ||
|
||
const setPolicy = (policy, setError, setInProgress) => { | ||
const setPolicy = async (policy, setError, setInProgress, fipsConfigurable) => { | ||
setInProgress(true); | ||
|
||
let promise; | ||
if (policy === "FIPS") { | ||
promise = cockpit.spawn(["fips-mode-setup", "--enable"], { superuser: "require", err: "message" }); | ||
} else { | ||
promise = cockpit.spawn(["fips-mode-setup", "--disable"], { superuser: "require", err: "message" }).then(() => | ||
cockpit.spawn(["update-crypto-policies", "--set", policy], { superuser: "require", err: "message" })); | ||
} | ||
try { | ||
if (policy === "FIPS") { | ||
cockpit.assert(fipsConfigurable, "calling setPolicy(FIPS) without fips-mode-setup"); | ||
await cockpit.spawn(["fips-mode-setup", "--enable"], { superuser: "require", err: "message" }); | ||
} else { | ||
if (fipsConfigurable) | ||
await cockpit.spawn(["fips-mode-setup", "--disable"], { superuser: "require", err: "message" }); | ||
await cockpit.spawn(["update-crypto-policies", "--set", policy], { superuser: "require", err: "message" }); | ||
} | ||
|
||
promise.then(() => cockpit.spawn(["shutdown", "--reboot", "now"], { superuser: "require", err: "message" })) | ||
.catch(error => setError(error)) | ||
.finally(() => setInProgress(false)); | ||
await cockpit.spawn(["shutdown", "--reboot", "now"], { superuser: "require", err: "message" }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically should use |
||
} catch (error) { | ||
setError(error); | ||
} finally { | ||
Comment on lines
+111
to
+113
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These 3 added lines are not executed by any test. |
||
setInProgress(false); | ||
} | ||
}; | ||
|
||
const CryptoPolicyDialog = ({ | ||
currentCryptoPolicy, | ||
fipsEnabled, | ||
fipsConfigurable, | ||
reApply, | ||
shaSubPolicyAvailable, | ||
}) => { | ||
|
@@ -125,6 +150,8 @@ const CryptoPolicyDialog = ({ | |
|
||
const policies = Object.keys(cryptopolicies) | ||
.filter(pol => pol.endsWith(':SHA1') ? shaSubPolicyAvailable : true) | ||
// cannot enable fips without fips-mode-setup | ||
.filter(pol => pol.startsWith("FIPS") ? fipsConfigurable : true) | ||
.map(policy => ({ | ||
name: policy, | ||
title: displayProfileText(policy), | ||
|
@@ -185,7 +212,8 @@ const CryptoPolicyDialog = ({ | |
<Flex spaceItems={{ default: 'spaceItemsSm' }} alignItems={{ default: 'alignItemsCenter' }}> | ||
{_("Applying new policy... This may take a few minutes.")} | ||
</Flex>} | ||
<Button id="crypto-policy-save-reboot" variant='primary' onClick={() => setPolicy(selected, setError, setInProgress)} | ||
<Button id="crypto-policy-save-reboot" variant='primary' | ||
onClick={() => setPolicy(selected, setError, setInProgress, fipsConfigurable)} | ||
isDisabled={inProgress} isLoading={inProgress} | ||
> | ||
{reApply ? _("Reapply and reboot") : _("Apply and reboot")} | ||
|
@@ -209,16 +237,18 @@ export const CryptoPolicyStatus = () => { | |
const Dialogs = useDialogs(); | ||
const [currentCryptoPolicy, setCurrentCryptoPolicy] = useState(null); | ||
const [fipsEnabled, setFipsEnabled] = useState(null); | ||
const [fipsConfigurable, setFipsConfigurable] = useState(null); | ||
|
||
useEffect(() => { | ||
if (currentCryptoPolicy === null) { | ||
cockpit.file("/etc/crypto-policies/state/current") | ||
.watch(content => setCurrentCryptoPolicy(content ? content.trim().split(':', 1)[0] : undefined)); | ||
} | ||
|
||
useInit(() => { | ||
cockpit.file("/etc/crypto-policies/state/current") | ||
.watch(content => setCurrentCryptoPolicy(content ? content.trim().split(':', 1)[0] : undefined)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This added line is not executed by any test. |
||
getFipsConfigurable().then(v => setFipsConfigurable(v)); | ||
cockpit.file("/proc/sys/crypto/fips_enabled").read() | ||
.then(content => setFipsEnabled(content ? content.trim() === "1" : false)); | ||
}, [currentCryptoPolicy]); | ||
}); | ||
|
||
if (currentCryptoPolicy === null || fipsConfigurable === null) | ||
return null; | ||
|
||
if (isInconsistentPolicy(currentCryptoPolicy, fipsEnabled)) { | ||
return ( | ||
|
@@ -232,6 +262,7 @@ export const CryptoPolicyStatus = () => { | |
<Button isInline variant="link" className="pf-v5-u-font-size-sm" | ||
onClick={() => Dialogs.show(<CryptoPolicyDialog currentCryptoPolicy={currentCryptoPolicy} | ||
fipsEnabled={fipsEnabled} | ||
fipsConfigurable={fipsConfigurable} | ||
reApply />)}> | ||
{_("Review cryptographic policy")} | ||
</Button> | ||
|
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.
This added line is not executed by any test.