Active Directory Support
This commit is contained in:
parent
10acebff46
commit
408ee0338a
91
src/modules/users/ActiveDirectoryJob.cpp
Normal file
91
src/modules/users/ActiveDirectoryJob.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ActiveDirectoryJob.h"
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "GlobalStorage.h"
|
||||||
|
#include "JobQueue.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/Permissions.h"
|
||||||
|
#include "utils/System.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
ActiveDirectoryJob::ActiveDirectoryJob(QStringList& activeDirectoryInfo)
|
||||||
|
: Calamares::Job()
|
||||||
|
, m_activeDirectoryInfo(activeDirectoryInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
ActiveDirectoryJob::prettyName() const
|
||||||
|
{
|
||||||
|
return tr( "Enroll system in Active Directory" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
ActiveDirectoryJob::prettyDescription() const
|
||||||
|
{
|
||||||
|
return tr( "Enroll system in Active Directory" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
ActiveDirectoryJob::prettyStatusMessage() const
|
||||||
|
{
|
||||||
|
return tr( "Enrolling system in Active Directory" );
|
||||||
|
}
|
||||||
|
|
||||||
|
Calamares::JobResult
|
||||||
|
ActiveDirectoryJob::exec()
|
||||||
|
{
|
||||||
|
QString username = m_activeDirectoryInfo.value(0);
|
||||||
|
QString password = m_activeDirectoryInfo.value(1);
|
||||||
|
QString domain = m_activeDirectoryInfo.value(2);
|
||||||
|
QString ip = m_activeDirectoryInfo.value(3);
|
||||||
|
|
||||||
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||||
|
QString rootMountPoint = gs ? gs->value("rootMountPoint").toString() : QString();
|
||||||
|
|
||||||
|
if (!ip.isEmpty()) {
|
||||||
|
QString hostsFilePath = !rootMountPoint.isEmpty() ? rootMountPoint + "/etc/hosts" : "/etc/hosts";
|
||||||
|
QFile hostsFile(hostsFilePath);
|
||||||
|
if (hostsFile.open(QIODevice::Append | QIODevice::Text)) {
|
||||||
|
QTextStream out(&hostsFile);
|
||||||
|
out << ip << " " << domain << "\n";
|
||||||
|
hostsFile.close();
|
||||||
|
} else {
|
||||||
|
return Calamares::JobResult::error("Failed to open /etc/hosts for writing.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString installPath = !rootMountPoint.isEmpty() ? rootMountPoint : "/";
|
||||||
|
QStringList args = {"join", domain, "-U", username, "--install=" + installPath, "--verbose"};
|
||||||
|
|
||||||
|
QProcess process;
|
||||||
|
process.start("realm", args);
|
||||||
|
process.waitForStarted();
|
||||||
|
|
||||||
|
if (!password.isEmpty()) {
|
||||||
|
process.write((password + "\n").toUtf8());
|
||||||
|
process.closeWriteChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
process.waitForFinished(-1);
|
||||||
|
|
||||||
|
if (process.exitCode() == 0) {
|
||||||
|
return Calamares::JobResult::ok();
|
||||||
|
} else {
|
||||||
|
QString errorOutput = process.readAllStandardError();
|
||||||
|
return Calamares::JobResult::error(QString("Failed to join realm: %1").arg(errorOutput));
|
||||||
|
}
|
||||||
|
}
|
29
src/modules/users/ActiveDirectoryJob.h
Normal file
29
src/modules/users/ActiveDirectoryJob.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Calamares is Free Software: see the License-Identifier above.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ACTIVEDIRECTORYJOB_H
|
||||||
|
#define ACTIVEDIRECTORYJOB_H
|
||||||
|
|
||||||
|
#include "Job.h"
|
||||||
|
|
||||||
|
class ActiveDirectoryJob : public Calamares::Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ActiveDirectoryJob( QStringList& activeDirectoryInfo );
|
||||||
|
QString prettyName() const override;
|
||||||
|
QString prettyDescription() const override;
|
||||||
|
QString prettyStatusMessage() const override;
|
||||||
|
Calamares::JobResult exec() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringList m_activeDirectoryInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ACTIVEDIRECTORYJOB_H */
|
@ -55,6 +55,7 @@ include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui)
|
|||||||
|
|
||||||
set(_users_src
|
set(_users_src
|
||||||
# Jobs
|
# Jobs
|
||||||
|
ActiveDirectoryJob.cpp
|
||||||
CreateUserJob.cpp
|
CreateUserJob.cpp
|
||||||
MiscJobs.cpp
|
MiscJobs.cpp
|
||||||
SetPasswordJob.cpp
|
SetPasswordJob.cpp
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "ActiveDirectoryJob.h"
|
||||||
#include "CreateUserJob.h"
|
#include "CreateUserJob.h"
|
||||||
#include "MiscJobs.h"
|
#include "MiscJobs.h"
|
||||||
#include "SetHostNameJob.h"
|
#include "SetHostNameJob.h"
|
||||||
@ -656,6 +657,59 @@ Config::setRootPasswordSecondary( const QString& s )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setActiveDirectoryUsed( bool used )
|
||||||
|
{
|
||||||
|
m_activeDirectoryUsed = used;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Config::getActiveDirectoryEnabled() const
|
||||||
|
{
|
||||||
|
return m_activeDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Config::getActiveDirectoryUsed() const
|
||||||
|
{
|
||||||
|
return m_activeDirectoryUsed && m_activeDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setActiveDirectoryAdminUsername( const QString & s )
|
||||||
|
{
|
||||||
|
m_activeDirectoryUsername = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setActiveDirectoryAdminPassword( const QString & s )
|
||||||
|
{
|
||||||
|
m_activeDirectoryPassword = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setActiveDirectoryDomain( const QString & s )
|
||||||
|
{
|
||||||
|
m_activeDirectoryDomain = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setActiveDirectoryIP( const QString & s )
|
||||||
|
{
|
||||||
|
m_activeDirectoryIP = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList&
|
||||||
|
Config::getActiveDirectory() const
|
||||||
|
{
|
||||||
|
m_activeDirectorySettings.clear();
|
||||||
|
m_activeDirectorySettings << m_activeDirectoryUsername
|
||||||
|
<< m_activeDirectoryPassword
|
||||||
|
<< m_activeDirectoryDomain
|
||||||
|
<< m_activeDirectoryIP;
|
||||||
|
return m_activeDirectorySettings;
|
||||||
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
Config::rootPassword() const
|
Config::rootPassword() const
|
||||||
{
|
{
|
||||||
@ -913,6 +967,9 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
|
|||||||
m_sudoStyle = Calamares::getBool( configurationMap, "sudoersConfigureWithGroup", false ) ? SudoStyle::UserAndGroup
|
m_sudoStyle = Calamares::getBool( configurationMap, "sudoersConfigureWithGroup", false ) ? SudoStyle::UserAndGroup
|
||||||
: SudoStyle::UserOnly;
|
: SudoStyle::UserOnly;
|
||||||
|
|
||||||
|
// Handle Active Directory enablement
|
||||||
|
m_activeDirectory = Calamares::getBool( configurationMap, "allowActiveDirectory", false );
|
||||||
|
|
||||||
// Handle *hostname* key and subkeys and legacy settings
|
// Handle *hostname* key and subkeys and legacy settings
|
||||||
{
|
{
|
||||||
bool ok = false; // Ignored
|
bool ok = false; // Ignored
|
||||||
@ -990,6 +1047,9 @@ Config::createJobs() const
|
|||||||
jobs.append( Calamares::job_ptr( j ) );
|
jobs.append( Calamares::job_ptr( j ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
j = new ActiveDirectoryJob( getActiveDirectory() );
|
||||||
|
jobs.append( Calamares::job_ptr( j ) );
|
||||||
|
|
||||||
j = new SetupGroupsJob( this );
|
j = new SetupGroupsJob( this );
|
||||||
jobs.append( Calamares::job_ptr( j ) );
|
jobs.append( Calamares::job_ptr( j ) );
|
||||||
|
|
||||||
|
@ -226,6 +226,12 @@ public:
|
|||||||
bool permitWeakPasswords() const { return m_permitWeakPasswords; }
|
bool permitWeakPasswords() const { return m_permitWeakPasswords; }
|
||||||
/// Current setting for "require strong password"?
|
/// Current setting for "require strong password"?
|
||||||
bool requireStrongPasswords() const { return m_requireStrongPasswords; }
|
bool requireStrongPasswords() const { return m_requireStrongPasswords; }
|
||||||
|
/// Is Active Directory enabled?
|
||||||
|
bool getActiveDirectoryEnabled() const;
|
||||||
|
/// Is it both enabled and activated?
|
||||||
|
bool getActiveDirectoryUsed() const;
|
||||||
|
/// Config for Active Directory
|
||||||
|
QStringList& getActiveDirectory() const;
|
||||||
|
|
||||||
const QList< GroupDescription >& defaultGroups() const { return m_defaultGroups; }
|
const QList< GroupDescription >& defaultGroups() const { return m_defaultGroups; }
|
||||||
/** @brief the names of all the groups for the current user
|
/** @brief the names of all the groups for the current user
|
||||||
@ -292,6 +298,12 @@ public Q_SLOTS:
|
|||||||
void setRootPassword( const QString& );
|
void setRootPassword( const QString& );
|
||||||
void setRootPasswordSecondary( const QString& );
|
void setRootPasswordSecondary( const QString& );
|
||||||
|
|
||||||
|
void setActiveDirectoryUsed( bool used );
|
||||||
|
void setActiveDirectoryAdminUsername( const QString& );
|
||||||
|
void setActiveDirectoryAdminPassword( const QString& );
|
||||||
|
void setActiveDirectoryDomain( const QString& );
|
||||||
|
void setActiveDirectoryIP( const QString& );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void userShellChanged( const QString& );
|
void userShellChanged( const QString& );
|
||||||
void autoLoginGroupChanged( const QString& );
|
void autoLoginGroupChanged( const QString& );
|
||||||
@ -343,6 +355,14 @@ private:
|
|||||||
|
|
||||||
bool m_isReady = false; ///< Used to reduce readyChanged signals
|
bool m_isReady = false; ///< Used to reduce readyChanged signals
|
||||||
|
|
||||||
|
mutable QStringList m_activeDirectorySettings;
|
||||||
|
bool m_activeDirectory = false;
|
||||||
|
bool m_activeDirectoryUsed = false;
|
||||||
|
QString m_activeDirectoryUsername;
|
||||||
|
QString m_activeDirectoryPassword;
|
||||||
|
QString m_activeDirectoryDomain;
|
||||||
|
QString m_activeDirectoryIP;
|
||||||
|
|
||||||
HostNameAction m_hostnameAction = HostNameAction::EtcHostname;
|
HostNameAction m_hostnameAction = HostNameAction::EtcHostname;
|
||||||
bool m_writeEtcHosts = false;
|
bool m_writeEtcHosts = false;
|
||||||
QString m_hostnameTemplate;
|
QString m_hostnameTemplate;
|
||||||
|
@ -162,6 +162,34 @@ UsersPage::UsersPage( Config* config, QWidget* parent )
|
|||||||
config, &Config::requireStrongPasswordsChanged, ui->checkBoxRequireStrongPassword, &QCheckBox::setChecked );
|
config, &Config::requireStrongPasswordsChanged, ui->checkBoxRequireStrongPassword, &QCheckBox::setChecked );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Active Directory is not checked or enabled by default
|
||||||
|
ui->useADCheckbox->setVisible(m_config->getActiveDirectoryEnabled());
|
||||||
|
ui->domainLabel->setVisible(false);
|
||||||
|
ui->domainField->setVisible(false);
|
||||||
|
ui->domainAdminLabel->setVisible(false);
|
||||||
|
ui->domainAdminField->setVisible(false);
|
||||||
|
ui->domainPasswordField->setVisible(false);
|
||||||
|
ui->domainPasswordLabel->setVisible(false);
|
||||||
|
ui->ipAddressField->setVisible(false);
|
||||||
|
ui->ipAddressLabel->setVisible(false);
|
||||||
|
|
||||||
|
connect(ui->useADCheckbox, &QCheckBox::toggled, [=](bool checked){
|
||||||
|
ui->domainLabel->setVisible(checked);
|
||||||
|
ui->domainField->setVisible(checked);
|
||||||
|
ui->domainAdminLabel->setVisible(checked);
|
||||||
|
ui->domainAdminField->setVisible(checked);
|
||||||
|
ui->domainPasswordField->setVisible(checked);
|
||||||
|
ui->domainPasswordLabel->setVisible(checked);
|
||||||
|
ui->ipAddressField->setVisible(checked);
|
||||||
|
ui->ipAddressLabel->setVisible(checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect( ui->domainField, &QLineEdit::textChanged, config, &Config::setActiveDirectoryDomain );
|
||||||
|
connect( ui->domainAdminField, &QLineEdit::textChanged, config, &Config::setActiveDirectoryAdminUsername );
|
||||||
|
connect( ui->domainPasswordField, &QLineEdit::textChanged, config, &Config::setActiveDirectoryAdminPassword );
|
||||||
|
connect( ui->ipAddressField, &QLineEdit::textChanged, config, &Config::setActiveDirectoryIP );
|
||||||
|
connect( ui->useADCheckbox, &QCheckBox::toggled, config, &Config::setActiveDirectoryUsed );
|
||||||
|
|
||||||
CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate );
|
CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate );
|
||||||
|
|
||||||
onReuseUserPasswordChanged( m_config->reuseUserPasswordForRoot() );
|
onReuseUserPasswordChanged( m_config->reuseUserPasswordForRoot() );
|
||||||
|
@ -603,6 +603,93 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>6</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="useADCheckbox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use Active Directory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="domainLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Domain:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="domainField"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="domainAdminLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Domain Administrator:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="domainAdminField"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="domainPasswordLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Password:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="domainPasswordField">
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ipAddressLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>IP Address (optional):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="ipAddressField"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_7">
|
<spacer name="verticalSpacer_7">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -265,6 +265,12 @@ hostname:
|
|||||||
template: "derp-${cpu}"
|
template: "derp-${cpu}"
|
||||||
forbidden_names: [ localhost ]
|
forbidden_names: [ localhost ]
|
||||||
|
|
||||||
|
# Enable Active Directory enrollment support (opt-in)
|
||||||
|
#
|
||||||
|
# This uses realmd to enroll the machine in an Active Directory server
|
||||||
|
# It requires realmd as a runtime dependency of Calamares, if enabled
|
||||||
|
allowActiveDirectory: false
|
||||||
|
|
||||||
presets:
|
presets:
|
||||||
fullName:
|
fullName:
|
||||||
# value: "OEM User"
|
# value: "OEM User"
|
||||||
|
@ -52,6 +52,7 @@ properties:
|
|||||||
writeHostsFile: { type: boolean, default: true }
|
writeHostsFile: { type: boolean, default: true }
|
||||||
template: { type: string, default: "${first}-${product}" }
|
template: { type: string, default: "${first}-${product}" }
|
||||||
forbidden_names: { type: array, items: { type: string } }
|
forbidden_names: { type: array, items: { type: string } }
|
||||||
|
allowActiveDirectory: { type: boolean, default: false }
|
||||||
|
|
||||||
# Presets
|
# Presets
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user