Skip to content
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

[Redesign add agent] Add and validate register agent commands #5622

Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,68 @@ import {
EuiCopy,
EuiIcon,
EuiSpacer,
EuiSwitch,
EuiSwitchEvent,
EuiText,
} from '@elastic/eui';
import React, { Fragment, useState } from 'react';
import React, { Fragment, useEffect, useState } from 'react';

interface ICommandSectionProps {
commandText: string;
showCommand: boolean;
onCopy: () => void;
os?: 'WINDOWS' | string;
password?: string;
}

export default function CommandOutput(props: ICommandSectionProps) {
const { commandText, showCommand, onCopy, os } = props;
const { commandText, showCommand, onCopy, os, password } = props;
const getHighlightCodeLanguage = (os: 'WINDOWS' | string) => {
if (os.toLowerCase() === 'windows') {
return 'powershell';
} else {
return 'bash';
}
};

const [language, setLanguage] = useState(getHighlightCodeLanguage(os || ''));
const [havePassword, setHavePassword] = useState(false);
const [showPassword, setShowPassword] = useState(false);

const onHandleCopy = (command: any) => {
onCopy && onCopy();
return command
return command; // the return is needed to avoid a bug in EuiCopy
};

const [commandToCopy, setCommandToCopy] = useState(commandText);
const [commandToShow, setCommandToShow] = useState(commandText);

useEffect(() => {
if (password) {
setHavePassword(true);
osdfucatePassword(password);
} else {
setHavePassword(false);
setCommandToShow(commandText);
}
}, [password, commandText, showPassword])

const osdfucatePassword = (password: string) => {
if(!password) return;
if(!commandText) return;

if(showPassword){
setCommandToShow(commandText);
}else{
// search password in commandText and replace with * for every character
const findPassword = commandText.search(password);
if (findPassword > -1) {
let command = commandText;
setCommandToShow(command.replace(/WAZUH_REGISTRATION_PASSWORD='([^']+)'/,`WAZUH_REGISTRATION_PASSWORD='${'*'.repeat(password.length)}'`));
}
}
}

const onChangeShowPassword = (event: EuiSwitchEvent) => {
setShowPassword(event.target.checked);
}

return (
<Fragment>
Expand All @@ -44,12 +77,15 @@ export default function CommandOutput(props: ICommandSectionProps) {
}}
language={getHighlightCodeLanguage(os || '')}
>
{showCommand ? commandText : ''}
{showCommand ? commandToShow : ''}
</EuiCodeBlock>
{showCommand && (
<EuiCopy textToCopy={commandText}>
{commandToCopy => (
<div className='copy-overlay' onClick={() => onHandleCopy(commandToCopy)}>
{copy => (
<div
className='copy-overlay'
onClick={() => onHandleCopy(copy())}
>
<p>
<EuiIcon type='copy' /> Copy command
</p>
Expand All @@ -59,6 +95,7 @@ export default function CommandOutput(props: ICommandSectionProps) {
)}
</div>
<EuiSpacer size='s' />
{showCommand && havePassword ? <EuiSwitch checked={showPassword} label='Show password' onChange={onChangeShowPassword}/> : null}
</EuiText>
</Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,14 @@ export const RegisterAgent = withReduxProvider(
const configuration = useSelector(
(state: { appConfig: { data: any } }) => state.appConfig.data,
);

const [wazuhVersion, setWazuhVersion] = useState('');
const [haveUdpProtocol, setHaveUdpProtocol] = useState<boolean | null>(
false,
);
const [haveConnectionSecure, setHaveConnectionSecure] = useState<
boolean | null
>(false);
const [loading, setLoading] = useState(false);
const [wazuhPassword, setWazuhPassword] = useState('');
const [groups, setGroups] = useState([]);
const [needsPassword, setNeedsPassword] = useState<boolean>(false);
const [hideTextPassword, setHideTextPassword] = useState<boolean>(false);

const initialFields: FormConfiguration = {
operatingSystemSelection: {
Expand Down Expand Up @@ -102,7 +97,6 @@ export const RegisterAgent = withReduxProvider(
const remoteConfig = await getMasterRemoteConfiguration();
if (remoteConfig) {
setHaveUdpProtocol(remoteConfig.isUdp);
setHaveConnectionSecure(remoteConfig.haveSecureConnection);
}
};

Expand All @@ -123,23 +117,19 @@ export const RegisterAgent = withReduxProvider(
const fetchData = async () => {
try {
const wazuhVersion = await getWazuhVersion();
let wazuhPassword = '';
let hideTextPassword = false;
await getRemoteConfig();
const authInfo = await getAuthInfo();
// get wazuh password configuration
let wazuhPassword = '';
const needsPassword = (authInfo.auth || {}).use_password === 'yes';
if (needsPassword) {
wazuhPassword =
configuration['enrollment.password'] ||
authInfo['authd.pass'] ||
'';
if (wazuhPassword) {
hideTextPassword = true;
}
}
const groups = await getGroups();
setNeedsPassword(needsPassword);
setHideTextPassword(hideTextPassword);
setWazuhPassword(wazuhPassword);
setWazuhVersion(wazuhVersion);
setGroups(groups);
Expand Down Expand Up @@ -218,13 +208,11 @@ export const RegisterAgent = withReduxProvider(
<Steps
form={form}
needsPassword={needsPassword}
hideTextPassword={hideTextPassword}
wazuhPassword={wazuhPassword}
osCard={osCard}
connection={{
isSecure: haveConnectionSecure ? true : false,
isUDP: haveUdpProtocol ? true : false,
}}
wazuhPassword={wazuhPassword}
/>
</EuiFlexItem>
)}
Expand Down
63 changes: 40 additions & 23 deletions public/controllers/register-agent/containers/steps/steps.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Fragment, useEffect, useState } from 'react';
import { EuiSteps } from '@elastic/eui';
import { EuiCallOut, EuiLink, EuiSteps, EuiTitle } from '@elastic/eui';
import './steps.scss';
import { OPERATING_SYSTEMS_OPTIONS } from '../../utils/register-agent-data';
import {
Expand Down Expand Up @@ -27,47 +27,49 @@ import {
getServerAddressStepStatus,
getOptionalParameterStepStatus,
showCommandsSections,
getPasswordStepStatus,
} from '../../services/register-agent-steps-status-services';
import { webDocumentationLink } from '../../../../../common/services/web_documentation';

interface IStepsProps {
needsPassword: boolean;
hideTextPassword: boolean;
form: UseFormReturn;
osCard: React.ReactElement;
connection: {
isUDP: boolean;
isSecure: boolean;
};
wazuhPassword: string;
}

export const Steps = ({
needsPassword,
hideTextPassword,
form,
osCard,
connection,
wazuhPassword,
}: IStepsProps) => {
const initialParsedFormValues = {
operatingSystem: {
name: '',
architecture: '',
},
optionalParams: {
agentGroups: '',
agentName: '',
serverAddress: '',
wazuhPassword,
protocol: connection.isUDP ? 'UDP' : '',
},
} as IParseRegisterFormValues;
const [registerAgentFormValues, setRegisterAgentFormValues] =
useState<IParseRegisterFormValues>({
operatingSystem: {
name: '',
architecture: '',
},
optionalParams: {
agentGroups: '',
agentName: '',
serverAddress: '',
wazuhPassword,
},
});
useState<IParseRegisterFormValues>(initialParsedFormValues);

useEffect(() => {
// get form values and parse them divided in OS and optional params
const registerAgentFormValuesParsed = parseRegisterAgentFormValues(
getRegisterAgentFormValues(form),
OPERATING_SYSTEMS_OPTIONS,
initialParsedFormValues,
);
setRegisterAgentFormValues(registerAgentFormValuesParsed);
setInstallCommandStepStatus(
Expand Down Expand Up @@ -99,7 +101,7 @@ export const Steps = ({
) {
selectOS(registerAgentFormValues.operatingSystem as tOperatingSystem);
}
setOptionalParams(registerAgentFormValues.optionalParams);
setOptionalParams({ ...registerAgentFormValues.optionalParams });
setInstallCommandWasCopied(false);
setStartCommandWasCopied(false);
}, [registerAgentFormValues]);
Expand Down Expand Up @@ -131,17 +133,32 @@ export const Steps = ({
children: <ServerAddressInput formField={form.fields.serverAddress} />,
status: getServerAddressStepStatus(form.fields),
},
...(!(!needsPassword || hideTextPassword)
...(needsPassword && !wazuhPassword
? [
{
title: <span className='stepTitle'>Wazuh password</span>,
children: (
<Fragment>
{
'No ha establecido una contraseña. Se le asigno una por defecto'
<EuiCallOut
color='warning'
title={
<span>
The Wazuh password is required but wasn't defined. Please check our{' '}
<EuiLink
target='_blank'
href={webDocumentationLink(
'user-manual/agent-enrollment/security-options/using-password-authentication.html',
)}
rel='noopener noreferrer'
>
steps
</EuiLink>
</span>
}
</Fragment>
iconType='iInCircle'
className='warningForAgentName'
/>
),
status: getPasswordStepStatus(form.fields),
},
]
: []),
Expand All @@ -151,7 +168,6 @@ export const Steps = ({
status: getOptionalParameterStepStatus(
form.fields,
installCommandWasCopied,
startCommandWasCopied,
),
},
{
Expand All @@ -166,6 +182,7 @@ export const Steps = ({
showCommand={showCommandsSections(form.fields)}
os={registerAgentFormValues.operatingSystem.name}
onCopy={() => setInstallCommandWasCopied(true)}
password={registerAgentFormValues.optionalParams.wazuhPassword}
/>
),
status: installCommandStepStatus,
Expand Down
Loading