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
Kms cluster encryption #7153
Kms cluster encryption #7153
Conversation
6de77aa
to
7213815
Compare
7213815
to
f064b54
Compare
cb38464
to
6dcb79e
Compare
6dcb79e
to
dc1c90a
Compare
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.
High level review for now
import { KMSProviders } from '../../constants/ocs-install'; | ||
import './kms-config.scss'; | ||
import * as _ from 'lodash'; | ||
import { advancedKMSModal } from '../modals/advanced-kms-modal/advanced-kms-modal'; | ||
import { setDispatch, parseURL } from './utils'; | ||
import { PencilAltIcon } from '@patternfly/react-icons'; | ||
import { global_palette_blue_300 as blueInfoColor } from '@patternfly/react-tokens/dist/js/global_palette_blue_300'; |
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.
Fix import hierarchy
<p>Connected to external key management service: {kms.name}</p> | ||
{encryption.advanced && ( | ||
<p className="ocs-install-wizard__review-encryption"> | ||
Connect to external key management service: {kms.name} |
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.
The KMS connection is done after clicking create, this should be better
Connect to external key management service: {kms.name} | |
External key management service: {kms.name} |
requestData.spec.security = { | ||
kms: { | ||
connectionDetailsConfigMap: 'ocs-vault-connection-details', | ||
tokenSecretName: 'ocs-kms-vault-token', |
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 would prefer to make ocs-kms-vault-token
a constant, since used at multiple places.
export const maxFileUploadSize = 4000000; | ||
export const fileSizeErrorMsg = 'Maximum file size exceeded. File limit is 4MB.'; |
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 better to prefix names with kms-
to understand what its for ?
@@ -71,7 +77,7 @@ export const CreateInternalCluster: React.FC<CreateInternalClusterProps> = ({ ma | |||
name: 'Configure', | |||
id: CreateStepsSC.CONFIGURE, | |||
component: <Configure state={state} dispatch={dispatch} mode={mode} />, | |||
enableNext: state.encryption.hasHandled && hasConfiguredNetwork, | |||
enableNext: state.encryption.hasHandled && hasConfiguredNetwork && state.kms.hasHandled, |
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.
Please remove any restriction from individual steps, until we push validation based wizard.
enableNext: state.encryption.hasHandled && hasConfiguredNetwork && state.kms.hasHandled, |
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 was decided to have Next
button blocked wrt validations in the wizard.
@cloudbehl @yuvalgalanti
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.
yes that's what was planned.
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.
We have navs still clickable, I thnk we should block them as well.
(Possibly in another PR)
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.
+1 @afreen23
Connect to external key management service: {kms.name} | ||
</p> | ||
)} | ||
<p>Encryption Level: {getEncryptionType(encryption)}</p> |
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.
<p>Encryption Level: {getEncryptionType(encryption)}</p> | |
<p>Encryption Level: {getEncryptionLevel(encryption)}</p> |
<p className="ocs-install-wizard__review-encryption">Enable Encryption</p> | ||
{encryption.advanced && kms.hasHandled && ( | ||
<p className="ocs-install-wizard__review-encryption"> | ||
Connect to external key management service: {kms.name} |
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.
Connect to external key management service: {kms.name} | |
External key management service: {kms.name} |
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.
As per UX, its Connected
since its connected after Create
button click, so changed it to Connect
.
<p className="ocs-install-wizard__review-encryption">Enable Encryption</p> | ||
{encryption.advanced && kms.hasHandled && ( | ||
<p>Connected to external key management service: {kms.name}</p> | ||
{encryption.advanced && ( |
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.
Why not kms.hasHandled
here ?
{encryption.advanced && (
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 have removed at the other place too, it's not required.
|
||
if (!checked) { | ||
kmsObject = initialState.kms; | ||
setDispatch(ActionType.SET_KMS_ENCRYPTION, kmsObject, mode, dispatch); |
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 would prefer to call it following, just to avoid confusion with root state dispatcher
setDispatch(ActionType.SET_KMS_ENCRYPTION, kmsObject, mode, dispatch); | |
setKms(ActionType.SET_KMS_ENCRYPTION, kmsObject, mode, dispatch); |
&__form-body { | ||
padding: var(--pf-global--spacer--md) 0 !important; | ||
} | ||
} |
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.
missing new line
const setServiceName = (name: string) => { | ||
setDispatch(ActionType.SET_KMS_ENCRYPTION, { ...kms, name }, mode, dispatch); | ||
}; |
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.
const setServiceName = (name: string) => { | |
setDispatch(ActionType.SET_KMS_ENCRYPTION, { ...kms, name }, mode, dispatch); | |
}; | |
const setServiceName = (name: string) => setDispatch(ActionType.SET_KMS_ENCRYPTION, { ...kms, name }, mode, dispatch); |
const validateAddressMessage = () => { | ||
if (kms.address === '') { | ||
return 'This is a required field'; | ||
} | ||
return 'Please enter a URL'; | ||
}; |
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.
const validateAddressMessage = () => { | |
if (kms.address === '') { | |
return 'This is a required field'; | |
} | |
return 'Please enter a URL'; | |
}; | |
const validateAddressMessage = () => (kms.address === '') ? | |
'This is a required field' : 'Please enter a URL'; |
const validatePort = () => { | ||
return _.isNaN(Number(kms.port)) || kms.port < 0 || !kms.port | ||
? ValidatedOptions.error | ||
: ValidatedOptions.default; | ||
}; |
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.
const validatePort = () => { | |
return _.isNaN(Number(kms.port)) || kms.port < 0 || !kms.port | |
? ValidatedOptions.error | |
: ValidatedOptions.default; | |
}; | |
const validatePort = () => _.isNaN(Number(kms.port)) || kms.port < 0 || !kms.port | |
? ValidatedOptions.error | |
: ValidatedOptions.default; |
const openAdvancedModal = () => { | ||
return advancedKMSModal({ |
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.
const openAdvancedModal = () => { | |
return advancedKMSModal({ | |
const openAdvancedModal = () => advancedKMSModal({ |
import { SecretModel } from '@console/internal/models'; | ||
import { SecretKind } from '@console/internal/module/k8s/types'; |
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.
Fix import order.
export const AdvancedKMSModal = withHandlePromise((props: AdvancedKMSModalProps) => { | ||
const { close, cancel, errorMessage, inProgress, state, dispatch, mode } = props; | ||
const { kms } = state; | ||
const [backendPath, setBackendPath] = React.useState(kms.backend || ''); |
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.
Why do we need another state here that is derived from another state? Can't we use dispatch and update the state over there.
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.
The advance modal has a Save
button, on clicking which the data has to be added in the state, to locally store data, I have added local states.
}; | ||
|
||
return ( | ||
<form |
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.
Why not use PF form?
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.
Then, we need to use PF form Modal as well. Console Modal's CSS breaks in PF4 form.
@@ -66,7 +66,11 @@ | |||
padding-left: var(--pf-global--spacer--lg); | |||
|
|||
&__form-body { | |||
padding: var(--pf-global--spacer--md); | |||
padding: var(--pf-global--spacer--md) !important; |
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.
Can we have a comment on why we are overriding using important
?
813c34c
to
e36ddc2
Compare
> | ||
<FormSelect | ||
value={kmsProvider} | ||
onChange={(e) => setKMSProvider(e)} |
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.
onChange={(e) => setKMSProvider(e)} | |
onChange={setKMSProvider} |
id="kms-provider-name" | ||
name="kms-provider-name" | ||
aria-label="kms-provider-name" | ||
isDisabled |
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.
we are not setting the isDisabled.
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.
For 4.7, it will always be disabled.
className="co-m-pane__form ocs-install-encryption__form-body" | ||
className="ocs-install-encryption__form-body" | ||
helperTextInvalid="This is a required field" | ||
validated={kms.name.valid ? ValidatedOptions.default : ValidatedOptions.error} |
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.
create a generic function and use it for all fields. Like isValid(name)
import { InternalClusterAction } from '../ocs-install/internal-mode/reducer'; | ||
import { KMSConfig, KMSConfigMap } from '../ocs-install/types'; | ||
|
||
export const parseURL = (url: string) => { |
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.
nit: can be put in a shared folder. Will do in next PR.
e36ddc2
to
fef77ec
Compare
@bipuladh will address this comment(#7153 (comment)) with the follow up PR: #7330. Please review the rest. |
@afreen23 @cloudbehl please review. |
/retest |
fef77ec
to
36b92b3
Compare
<FormSelect | ||
value={kmsProvider} | ||
onChange={setKMSProvider} | ||
id="kms-provider-name" |
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.
id
needs to match with FormGroup
id="kms-provider-name" | |
id="kms-provider" |
onChange={setAddress} | ||
className="ocs-install-kms__form-address--padding" | ||
type="url" | ||
id="kms-address" |
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.
here as well.
id="kms-address" | |
id="kms-service-address" |
<FormGroup | ||
fieldId="kms-service-address-port" | ||
label="Port" | ||
className="ocs-install-kms__form-port ocs-install-encryption__form-body--small-padding" | ||
helperTextInvalid={validatePortMessage()} | ||
validated={isValid(kms.port.valid)} | ||
isRequired | ||
> | ||
<TextInput | ||
value={kms.port.value} | ||
onChange={setAddressPort} | ||
type="text" | ||
id="kms-address-port" | ||
name="kms-address-port" | ||
isRequired | ||
validated={isValid(kms.port.valid)} | ||
/> | ||
</FormGroup> | ||
</div> | ||
<FormGroup | ||
fieldId="kms-service-token" | ||
label="Token" | ||
className="ocs-install-encryption__form-body" | ||
helperTextInvalid="This is a required field" | ||
validated={isValid(kms.token.valid)} | ||
isRequired | ||
> | ||
<TextInput | ||
value={kms.token.value} | ||
onChange={setToken} | ||
type="password" | ||
id="kms-token" | ||
name="kms-token" | ||
isRequired | ||
validated={isValid(kms.token.valid)} |
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.
Fix id names
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [kms.name]); | ||
const serviceName = (name: string) => { |
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.
const serviceName = (name: string) => { | |
const setServiceName = (name: string) => { |
if (caCertificate && caCertificate !== '') { | ||
kmsAdvanced.caCert = caSecret; | ||
kmsAdvanced.caCertFile = caCertificateFile; | ||
} else { | ||
kmsAdvanced.caCert = null; | ||
kmsAdvanced.caCertFile = ''; | ||
} | ||
|
||
if (clientCertificate && clientCertificate !== '') { | ||
kmsAdvanced.clientCert = clientCertSecret; | ||
kmsAdvanced.clientCertFile = clientCertificateFile; | ||
} else { | ||
kmsAdvanced.clientCert = null; | ||
kmsAdvanced.clientCertFile = ''; | ||
} | ||
|
||
if (clientKey && clientCertificate !== '') { | ||
kmsAdvanced.clientKey = clientKeySecret; | ||
kmsAdvanced.clientKeyFile = clientKeyFile; | ||
} else { | ||
kmsAdvanced.clientKey = null; | ||
kmsAdvanced.clientKeyFile = ''; | ||
} |
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.
Does not setting value helps here ?
Because anyways you are setting state. I think you can avoid the guard here
if (encryption.advanced && kms.hasHandled) { | ||
promises.push(...kmsResources(kms)); | ||
} | ||
await Promise.all(promises).then(() => k8sCreate(OCSServiceModel, storageCluster)); |
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 understand its not the part of PR, but this is a minor :)
await Promise.all(promises).then(() => k8sCreate(OCSServiceModel, storageCluster)); | |
await Promise.all(promises).then(() => k8sCreate(StorageClusterModel, storageCluster)); |
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.
No worries to take in another PR, this needs fix at various places.
}; | ||
|
||
return ( | ||
<form |
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.
Then, we need to use PF form Modal as well. Console Modal's CSS breaks in PF4 form.
@@ -15,6 +15,8 @@ export const requestedCapacityTooltip = | |||
'The backing storage requested will be higher as it will factor in the requested capacity, replica factor, and fault tolerant costs associated with the requested capacity.'; | |||
export const encryptionTooltip = | |||
'The storage cluster encryption level can be set to include all components under the cluster (including storage class and PVs) or to include only storage class encryption. PV encryption can use an auth token that will be used with the KMS configuration to allow multi-tenancy.'; | |||
export const vaultNamespaceTooltip = | |||
'Vault enterprise namespaces are isolated environments that functionally exist as "Vaults within a Vault." They have separate login paths and support creating and managing data isolated to their namespace.'; |
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.
'Vault enterprise namespaces are isolated environments that functionally exist as "Vaults within a Vault." They have separate login paths and support creating and managing data isolated to their namespace.'; | |
'Vault enterprise namespaces are isolated environments that functionally exist as "Vaults within a Vault". They have separate login paths and support creating and managing data isolated to their namespace.'; |
36b92b3
to
36a0469
Compare
if (kmsEnable) { | ||
requestData.spec.encryption = { | ||
...requestData.spec.encryption, | ||
kms: { | ||
enable: true, | ||
}, | ||
}; | ||
} |
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.
Just for consistency, can you use Object.assign as well similar to arbiter and network?
@@ -38,6 +39,7 @@ export type InternalClusterAction = | |||
| { type: ActionType.SET_ENCRYPTION; payload: EncryptionType } | |||
// KMS action | |||
| { type: ActionType.SET_KMS_ENCRYPTION; payload: KMSConfig } | |||
| { type: ActionType.CLEAR_KMS_STATE; payload?: KMSConfig } |
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.
Why payload optional ? Can't we pass empty params to the same action , used to set kms ActionType.SET_KMS_ENCRYPTION
?
}; | ||
|
||
return ( | ||
<Form onSubmit={submit} key="pool-form-modal"> |
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.
nit: pool-form-modal
<Form onSubmit={submit} key="pool-form-modal"> | |
<Form onSubmit={submit} key=""> |
export const kmsMaxFileUploadSize = 4000000; | ||
export const kmsFileSizeErrorMsg = 'Maximum file size exceeded. File limit is 4MB.'; | ||
export const KMSConfigMapName = 'ocs-kms-connection-details'; | ||
export const KMSSecretName = 'ocs-kms-token'; |
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.
Lets be consistent with names.
export const kmsMaxFileUploadSize = 4000000; | |
export const kmsFileSizeErrorMsg = 'Maximum file size exceeded. File limit is 4MB.'; | |
export const KMSConfigMapName = 'ocs-kms-connection-details'; | |
export const KMSSecretName = 'ocs-kms-token'; | |
export const KMSMaxFileUploadSize = 4000000; | |
export const KMSFileSizeErrorMsg = 'Maximum file size exceeded. File limit is 4MB.'; | |
export const KMSConfigMapName = 'ocs-kms-connection-details'; | |
export const KMSSecretName = 'ocs-kms-token'; |
Signed-off-by: Kanika Murarka <kmurarka@redhat.com>
36a0469
to
226c6f3
Compare
/test e2e-gcp-console |
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.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: a2batic, afreen23 The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Merged after: #7062