diff --git a/gsa/src/gmp/models/credential.js b/gsa/src/gmp/models/credential.js
index 948821a44d..13af869c0b 100644
--- a/gsa/src/gmp/models/credential.js
+++ b/gsa/src/gmp/models/credential.js
@@ -37,6 +37,8 @@ export const SSH_CREDENTIAL_TYPES = [
USERNAME_SSH_KEY_CREDENTIAL_TYPE,
];
+export const SSH_ELEVATE_CREDENTIAL_TYPES = [USERNAME_PASSWORD_CREDENTIAL_TYPE];
+
export const SMB_CREDENTIAL_TYPES = [USERNAME_PASSWORD_CREDENTIAL_TYPE];
export const ESXI_CREDENTIAL_TYPES = [USERNAME_PASSWORD_CREDENTIAL_TYPE];
diff --git a/gsa/src/web/pages/targets/component.js b/gsa/src/web/pages/targets/component.js
index 6fcaf621c5..4f6eb1603d 100644
--- a/gsa/src/web/pages/targets/component.js
+++ b/gsa/src/web/pages/targets/component.js
@@ -54,9 +54,8 @@ class TargetComponent extends React.Component {
};
this.openCredentialsDialog = this.openCredentialsDialog.bind(this);
- this.handleCloseCredentialsDialog = this.handleCloseCredentialsDialog.bind(
- this,
- );
+ this.handleCloseCredentialsDialog =
+ this.handleCloseCredentialsDialog.bind(this);
this.openPortListDialog = this.openPortListDialog.bind(this);
this.handleClosePortListDialog = this.handleClosePortListDialog.bind(this);
this.openTargetDialog = this.openTargetDialog.bind(this);
@@ -65,14 +64,14 @@ class TargetComponent extends React.Component {
this.handleCreateCredential = this.handleCreateCredential.bind(this);
this.handleCreatePortList = this.handleCreatePortList.bind(this);
this.handlePortListChange = this.handlePortListChange.bind(this);
- this.handleEsxiCredentialChange = this.handleEsxiCredentialChange.bind(
- this,
- );
+ this.handleEsxiCredentialChange =
+ this.handleEsxiCredentialChange.bind(this);
this.handleSshCredentialChange = this.handleSshCredentialChange.bind(this);
+ this.handleSshElevateCredentialChange =
+ this.handleSshElevateCredentialChange.bind(this);
this.handleSmbCredentialChange = this.handleSmbCredentialChange.bind(this);
- this.handleSnmpCredentialChange = this.handleSnmpCredentialChange.bind(
- this,
- );
+ this.handleSnmpCredentialChange =
+ this.handleSnmpCredentialChange.bind(this);
}
openCredentialsDialog({id_field, types, title}) {
@@ -128,6 +127,7 @@ class TargetComponent extends React.Component {
smb_credential_id: id_or__(entity.smb_credential),
snmp_credential_id: id_or__(entity.snmp_credential),
ssh_credential_id: id_or__(entity.ssh_credential),
+ ssh_elevate_credential_id: id_or__(entity.ssh_elevate_credential_id),
});
});
} else {
@@ -154,6 +154,7 @@ class TargetComponent extends React.Component {
smb_credential_id: undefined,
snmp_credential_id: undefined,
ssh_credential_id: undefined,
+ ssh_elevate_credential_id: undefined,
target_source: undefined,
target_exclude_source: undefined,
target_title: _('New Target'),
@@ -269,6 +270,10 @@ class TargetComponent extends React.Component {
this.setState({ssh_credential_id});
}
+ handleSshElevateCredentialChange(ssh_elevate_credential_id) {
+ this.setState({ssh_elevate_credential_id});
+ }
+
handleSnmpCredentialChange(snmp_credential_id) {
this.setState({snmp_credential_id});
}
@@ -327,6 +332,7 @@ class TargetComponent extends React.Component {
smb_credential_id,
snmp_credential_id,
ssh_credential_id,
+ ssh_elevate_credential_id,
target_source,
target_exclude_source,
target_title,
@@ -377,6 +383,7 @@ class TargetComponent extends React.Component {
smb_credential_id={smb_credential_id}
snmp_credential_id={snmp_credential_id}
ssh_credential_id={ssh_credential_id}
+ ssh_elevate_credential_id={ssh_elevate_credential_id}
target_source={target_source}
target_exclude_source={target_exclude_source}
title={target_title}
@@ -388,6 +395,9 @@ class TargetComponent extends React.Component {
onSshCredentialChange={this.handleSshCredentialChange}
onEsxiCredentialChange={this.handleEsxiCredentialChange}
onSmbCredentialChange={this.handleSmbCredentialChange}
+ onSshElevateCredentialChange={
+ this.handleSshElevateCredentialChange
+ }
onSave={d => {
this.handleInteraction();
return save(d).then(() => this.closeTargetDialog());
diff --git a/gsa/src/web/pages/targets/dialog.js b/gsa/src/web/pages/targets/dialog.js
index a5bb8118c0..4a446f655b 100644
--- a/gsa/src/web/pages/targets/dialog.js
+++ b/gsa/src/web/pages/targets/dialog.js
@@ -17,6 +17,8 @@
*/
import React from 'react';
+import styled from 'styled-components';
+
import {_, _l} from 'gmp/locale/lang';
import {NO_VALUE, YES_VALUE} from 'gmp/parser';
@@ -39,6 +41,8 @@ import NewIcon from 'web/components/icon/newicon';
import Divider from 'web/components/layout/divider';
import Layout from 'web/components/layout/layout';
+import Theme from 'web/utils/theme';
+
import {
snmp_credential_filter,
ssh_credential_filter,
@@ -47,6 +51,7 @@ import {
SNMP_CREDENTIAL_TYPES,
SSH_CREDENTIAL_TYPES,
USERNAME_PASSWORD_CREDENTIAL_TYPE,
+ SSH_ELEVATE_CREDENTIAL_TYPES,
} from 'gmp/models/credential';
const DEFAULT_PORT = 22;
@@ -89,6 +94,12 @@ const NEW_SSH = {
title: _l('Create new SSH credential'),
};
+const NEW_SSH_ELEVATE = {
+ id_field: 'ssh_elevate_credential_id',
+ types: SSH_ELEVATE_CREDENTIAL_TYPES,
+ title: _l('Create new credential for root privileges on target system'), // what is a shorter, more explanatory title?
+};
+
const NEW_SMB = {
id_field: 'smb_credential_id',
title: _l('Create new SMB credential'),
@@ -107,6 +118,10 @@ const NEW_SNMP = {
types: SNMP_CREDENTIAL_TYPES,
};
+const ElevatePrivilegeText = styled(Layout)`
+ color: ${Theme.darkRed};
+`;
+
const TargetDialog = ({
alive_tests = ALIVE_TESTS_DEFAULT,
allowSimultaneousIPs = YES_VALUE,
@@ -127,6 +142,7 @@ const TargetDialog = ({
smb_credential_id = UNSET_VALUE,
snmp_credential_id = UNSET_VALUE,
ssh_credential_id = UNSET_VALUE,
+ ssh_elevate_credential_id = UNSET_VALUE,
target_source = 'manual',
target_exclude_source = 'manual',
title = _('New Target'),
@@ -139,6 +155,7 @@ const TargetDialog = ({
onSmbCredentialChange,
onEsxiCredentialChange,
onSnmpCredentialChange,
+ onSshElevateCredentialChange,
...initial
}) => {
const ssh_credentials = credentials.filter(ssh_credential_filter);
@@ -170,6 +187,7 @@ const TargetDialog = ({
smb_credential_id,
snmp_credential_id,
ssh_credential_id,
+ ssh_elevate_credential_id,
};
return (
@@ -342,34 +360,61 @@ const TargetDialog = ({
)}
{capabilities.mayOp('get_credentials') && (
-
-
-
- {_('on port')}
-
- {!in_use && (
-
-
+
+
+
+ {_('on port')}
+
+ {!in_use && (
+
+
+
+ )}
+
+
+ {state.ssh_credential_id !== UNSET_VALUE && (
+
+
+
+ {_('Elevate privileges')}
+
+
-
- )}
-
-
+ {!in_use && (
+
+
+
+ )}
+
+
+ )}
+
)}
{capabilities.mayOp('get_credentials') && (
@@ -485,6 +530,7 @@ TargetDialog.propTypes = {
smb_credential_id: PropTypes.idOrZero,
snmp_credential_id: PropTypes.idOrZero,
ssh_credential_id: PropTypes.idOrZero,
+ ssh_elevate_credential_id: PropTypes.idOrZero,
target_exclude_source: PropTypes.oneOf(['manual', 'file']),
target_source: PropTypes.oneOf(['manual', 'file', 'asset_hosts']),
title: PropTypes.string,
@@ -497,6 +543,7 @@ TargetDialog.propTypes = {
onSmbCredentialChange: PropTypes.func.isRequired,
onSnmpCredentialChange: PropTypes.func.isRequired,
onSshCredentialChange: PropTypes.func.isRequired,
+ onSshElevateCredentialChange: PropTypes.func.isRequired,
};
export default withCapabilities(TargetDialog);