mirror of https://github.com/portainer/portainer
389 lines
20 KiB
HTML
389 lines
20 KiB
HTML
<rd-header>
|
|
<rd-header-title title-text="Authentication settings"></rd-header-title>
|
|
<rd-header-content> <a ui-sref="portainer.settings">Settings</a> > Authentication </rd-header-content>
|
|
</rd-header>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<rd-widget>
|
|
<rd-widget-header icon="fa-users" title-text="Authentication"></rd-widget-header>
|
|
<rd-widget-body>
|
|
<form class="form-horizontal">
|
|
<div class="col-sm-12 form-section-title">
|
|
Configuration
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="user_timeout" class="col-sm-2 control-label text-left">
|
|
Session lifetime
|
|
<portainer-tooltip message="Time before users are forced to relogin."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-10">
|
|
<select
|
|
id="user_timeout"
|
|
class="form-control"
|
|
ng-model="settings.UserSessionTimeout"
|
|
ng-options="opt.value as opt.key for opt in state.availableUserSessionTimeoutOptions"
|
|
></select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small">
|
|
Changing from default is only recommended if you have additional layers of authentication in front of Portainer.
|
|
</span>
|
|
</div>
|
|
<div class="col-sm-12 form-section-title">
|
|
Authentication method
|
|
</div>
|
|
<div class="form-group"></div>
|
|
<div class="form-group" style="margin-bottom: 0;">
|
|
<div class="boxselector_wrapper">
|
|
<div>
|
|
<input type="radio" id="registry_quay" ng-model="settings.AuthenticationMethod" ng-value="1" />
|
|
<label for="registry_quay">
|
|
<div class="boxselector_header">
|
|
<i class="fa fa-users" aria-hidden="true" style="margin-right: 2px;"></i>
|
|
Internal
|
|
</div>
|
|
<p>Internal authentication mechanism</p>
|
|
</label>
|
|
</div>
|
|
<div>
|
|
<input type="radio" id="registry_custom" ng-model="settings.AuthenticationMethod" ng-value="2" />
|
|
<label for="registry_custom">
|
|
<div class="boxselector_header">
|
|
<i class="fa fa-users" aria-hidden="true" style="margin-right: 2px;"></i>
|
|
LDAP
|
|
</div>
|
|
<p>LDAP authentication</p>
|
|
</label>
|
|
</div>
|
|
<div>
|
|
<input type="radio" id="registry_auth" ng-model="settings.AuthenticationMethod" ng-value="3" />
|
|
<label for="registry_auth">
|
|
<div class="boxselector_header">
|
|
<i class="fa fa-users" aria-hidden="true" style="margin-right: 2px;"></i>
|
|
OAuth
|
|
</div>
|
|
<p>OAuth authentication</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="settings.AuthenticationMethod === 1">
|
|
<div class="col-sm-12 form-section-title">
|
|
Information
|
|
</div>
|
|
<div class="form-group col-sm-12 text-muted small">
|
|
When using internal authentication, Portainer will encrypt user passwords and store credentials locally.
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="settings.AuthenticationMethod === 2">
|
|
<div>
|
|
<div class="col-sm-12 form-section-title">
|
|
Information
|
|
</div>
|
|
<div class="form-group col-sm-12 text-muted small">
|
|
When using LDAP authentication, Portainer will delegate user authentication to a LDAP server and fallback to internal authentication if LDAP authentication fails.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-section-title">
|
|
LDAP configuration
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left">
|
|
LDAP Server
|
|
<portainer-tooltip position="bottom" message="URL or IP address of the LDAP server."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input type="text" class="form-control" id="ldap_url" ng-model="formValues.LDAPSettings.URL" placeholder="e.g. 10.0.0.10:389 or myldap.domain.tld:389" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Anonymous mode-->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label for="anonymous_mode" class="control-label text-left">
|
|
Anonymous mode
|
|
<portainer-tooltip position="bottom" message="Enable this option if the server is configured for Anonymous access."></portainer-tooltip>
|
|
</label>
|
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" id="anonymous_mode" ng-model="formValues.LDAPSettings.AnonymousMode" /><i></i> </label>
|
|
</div>
|
|
</div>
|
|
<!-- !Anonymous mode-->
|
|
|
|
<div ng-if="!formValues.LDAPSettings.AnonymousMode">
|
|
<div class="form-group">
|
|
<label for="ldap_username" class="col-sm-3 col-lg-2 control-label text-left">
|
|
Reader DN
|
|
<portainer-tooltip position="bottom" message="Account that will be used to search for users."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="ldap_username"
|
|
ng-model="formValues.LDAPSettings.ReaderDN"
|
|
placeholder="cn=readonly-account,dc=ldap,dc=domain,dc=tld"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="ldap_password" class="col-sm-3 col-lg-2 control-label text-left">
|
|
Password
|
|
<portainer-tooltip position="bottom" message="If you do not enter a password, Portainer will leave the current password unchanged."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input type="password" class="form-control" id="ldap_password" ng-model="formValues.LDAPSettings.Password" placeholder="password" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group" ng-if="!formValues.LDAPSettings.TLSConfig.TLS && !formValues.LDAPSettings.StartTLS">
|
|
<label for="ldap_password" class="col-sm-3 col-lg-2 control-label text-left">
|
|
Connectivity check
|
|
<i class="fa fa-check green-icon" style="margin-left: 5px;" ng-if="state.successfulConnectivityCheck"></i>
|
|
<i class="fa fa-times red-icon" style="margin-left: 5px;" ng-if="state.failedConnectivityCheck"></i>
|
|
</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary btn-sm"
|
|
ng-disabled="(state.connectivityCheckInProgress) || (!formValues.LDAPSettings.URL) || ((!formValues.LDAPSettings.ReaderDN || !formValues.LDAPSettings.Password) && !formValues.LDAPSettings.AnonymousMode)"
|
|
ng-click="LDAPConnectivityCheck()"
|
|
button-spinner="state.connectivityCheckInProgress"
|
|
>
|
|
<span ng-hide="state.connectivityCheckInProgress">Test connectivity</span>
|
|
<span ng-show="state.connectivityCheckInProgress">Testing connectivity...</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-section-title">
|
|
LDAP security
|
|
</div>
|
|
|
|
<!-- starttls -->
|
|
<div class="form-group" ng-if="!formValues.LDAPSettings.TLSConfig.TLS">
|
|
<div class="col-sm-12">
|
|
<label for="tls" class="control-label text-left">
|
|
Use StartTLS
|
|
<portainer-tooltip
|
|
position="bottom"
|
|
message="Enable this option if want to use StartTLS to secure the connection to the server. Ignored if Use TLS is selected."
|
|
></portainer-tooltip>
|
|
</label>
|
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="formValues.LDAPSettings.StartTLS" /><i></i> </label>
|
|
</div>
|
|
</div>
|
|
<!-- !starttls -->
|
|
|
|
<!-- tls-checkbox -->
|
|
<div class="form-group" ng-if="!formValues.LDAPSettings.StartTLS">
|
|
<div class="col-sm-12">
|
|
<label for="tls" class="control-label text-left">
|
|
Use TLS
|
|
<portainer-tooltip position="bottom" message="Enable this option if you need to specify TLS certificates to connect to the LDAP server."></portainer-tooltip>
|
|
</label>
|
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="formValues.LDAPSettings.TLSConfig.TLS" /><i></i> </label>
|
|
</div>
|
|
</div>
|
|
<!-- !tls-checkbox -->
|
|
|
|
<!-- tls-skip-verify -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label for="tls" class="control-label text-left">
|
|
Skip verification of server certificate
|
|
<portainer-tooltip position="bottom" message="Skip the verification of the server TLS certificate. Not recommended on unsecured networks."></portainer-tooltip>
|
|
</label>
|
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="formValues.LDAPSettings.TLSConfig.TLSSkipVerify" /><i></i> </label>
|
|
</div>
|
|
</div>
|
|
<!-- !tls-skip-verify -->
|
|
|
|
<!-- tls-certs -->
|
|
<div ng-if="formValues.LDAPSettings.TLSConfig.TLS || formValues.LDAPSettings.StartTLS">
|
|
<!-- ca-input -->
|
|
<div class="form-group" ng-if="!formValues.LDAPSettings.TLSConfig.TLSSkipVerify">
|
|
<label class="col-sm-2 control-label text-left">TLS CA certificate</label>
|
|
<div class="col-sm-10">
|
|
<button class="btn btn-sm btn-primary" ngf-select ng-model="formValues.TLSCACert">Select file</button>
|
|
<span style="margin-left: 5px;">
|
|
{{ formValues.TLSCACert.name }}
|
|
<i class="fa fa-check green-icon" ng-if="formValues.TLSCACert && formValues.TLSCACert === formValues.LDAPSettings.TLSConfig.TLSCACert" aria-hidden="true"></i>
|
|
<i class="fa fa-times red-icon" ng-if="!formValues.TLSCACert" aria-hidden="true"></i>
|
|
<i class="fa fa-circle-notch fa-spin" ng-if="state.uploadInProgress"></i>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<!-- !ca-input -->
|
|
</div>
|
|
<!-- !tls-certs -->
|
|
|
|
<div class="form-group" ng-if="formValues.LDAPSettings.TLSConfig.TLS || formValues.LDAPSettings.StartTLS">
|
|
<label for="ldap_password" class="col-sm-3 col-lg-2 control-label text-left">
|
|
Connectivity check
|
|
<i class="fa fa-check green-icon" style="margin-left: 5px;" ng-if="state.successfulConnectivityCheck"></i>
|
|
<i class="fa fa-times red-icon" style="margin-left: 5px;" ng-if="state.failedConnectivityCheck"></i>
|
|
</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary btn-sm"
|
|
ng-click="LDAPConnectivityCheck()"
|
|
ng-disabled="(!formValues.LDAPSettings.URL) || (!formValues.TLSCACert && !formValues.LDAPSettings.TLSConfig.TLSSkipVerify) || ((!formValues.LDAPSettings.ReaderDN || !formValues.LDAPSettings.Password) && !formValues.LDAPSettings.AnonymousMode)"
|
|
>Test connectivity</button
|
|
>
|
|
<i id="connectivityCheckSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-section-title">
|
|
Automatic user provisioning
|
|
</div>
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small">
|
|
With automatic user provisioning enabled, Portainer will create user(s) automatically with standard user role and assign them to team(s) which matches to LDAP group
|
|
name(s). If disabled, users must be created in Portainer beforehand.
|
|
</span>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label for="tls" class="control-label text-left">
|
|
Automatic user provisioning
|
|
</label>
|
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="formValues.LDAPSettings.AutoCreateUsers" /><i></i> </label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-section-title">
|
|
User search configurations
|
|
</div>
|
|
|
|
<!-- search-settings -->
|
|
<div ng-repeat="config in formValues.LDAPSettings.SearchSettings | limitTo: (1 - formValues.LDAPSettings.SearchSettings)" style="margin-top: 5px;">
|
|
<div class="form-group" ng-if="$index > 0">
|
|
<span class="col-sm-12 text-muted small">
|
|
Extra search configuration
|
|
</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="ldap_basedn_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
|
|
Base DN
|
|
<portainer-tooltip position="bottom" message="The distinguished name of the element from which the LDAP server will search for users."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-8 col-md-4">
|
|
<input type="text" class="form-control" id="ldap_basedn_{{ $index }}" ng-model="config.BaseDN" placeholder="dc=ldap,dc=domain,dc=tld" />
|
|
</div>
|
|
|
|
<label for="ldap_username_att_{{ $index }}" class="col-sm-4 col-md-3 col-lg-2 margin-sm-top control-label text-left">
|
|
Username attribute
|
|
<portainer-tooltip position="bottom" message="LDAP attribute which denotes the username."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-8 col-md-3 col-lg-4 margin-sm-top">
|
|
<input type="text" class="form-control" id="ldap_username_att_{{ $index }}" ng-model="config.UserNameAttribute" placeholder="uid" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_filter_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
|
|
Filter
|
|
<portainer-tooltip position="bottom" message="The LDAP search filter used to select user elements, optional."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-7 col-md-9">
|
|
<input type="text" class="form-control" id="ldap_filter_{{ $index }}" ng-model="config.Filter" placeholder="(objectClass=account)" />
|
|
</div>
|
|
<div class="col-sm-1" ng-if="$index > 0">
|
|
<button class="btn btn-sm btn-danger" type="button" ng-click="removeSearchConfiguration($index)">
|
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addSearchConfiguration()">
|
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> add user search configuration
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<!-- !search-settings -->
|
|
|
|
<div class="col-sm-12 form-section-title">
|
|
Group search configurations
|
|
</div>
|
|
|
|
<!-- group-search-settings -->
|
|
<div ng-repeat="groupConfig in formValues.LDAPSettings.GroupSearchSettings | limitTo: (1 - formValues.LDAPSettings.GroupSearchSettings)" style="margin-top: 5px;">
|
|
<div class="form-group" ng-if="$index > 0">
|
|
<span class="col-sm-12 text-muted small">
|
|
Extra search configuration
|
|
</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="ldap_group_basedn_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
|
|
Group Base DN
|
|
<portainer-tooltip position="bottom" message="The distinguished name of the element from which the LDAP server will search for groups."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-8 col-md-4">
|
|
<input type="text" class="form-control" id="ldap_group_basedn_{{ $index }}" ng-model="groupConfig.GroupBaseDN" placeholder="dc=ldap,dc=domain,dc=tld" />
|
|
</div>
|
|
|
|
<label for="ldap_group_att_{{ $index }}" class="col-sm-4 col-md-3 col-lg-2 margin-sm-top control-label text-left">
|
|
Group Membership Attribute
|
|
<portainer-tooltip position="bottom" message="LDAP attribute which denotes the group membership."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-8 col-md-3 col-lg-4 margin-sm-top">
|
|
<input type="text" class="form-control" id="ldap_group_att_{{ $index }}" ng-model="groupConfig.GroupAttribute" placeholder="member" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_group_filter_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
|
|
Group Filter
|
|
<portainer-tooltip position="bottom" message="The LDAP search filter used to select group elements, optional."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-7 col-md-9">
|
|
<input type="text" class="form-control" id="ldap_group_filter_{{ $index }}" ng-model="groupConfig.GroupFilter" placeholder="(objectClass=account)" />
|
|
</div>
|
|
<div class="col-sm-1" ng-if="$index > 0">
|
|
<button class="btn btn-sm btn-danger" type="button" ng-click="removeGroupSearchConfiguration($index)">
|
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addGroupSearchConfiguration()">
|
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> add group search configuration
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<!-- !group-search-settings -->
|
|
</div>
|
|
|
|
<oauth-settings ng-if="isOauthEnabled()" settings="OAuthSettings" teams="teams"></oauth-settings>
|
|
|
|
<!-- actions -->
|
|
<div class="col-sm-12 form-section-title">
|
|
Actions
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<button type="button" class="btn btn-primary btn-sm" ng-click="saveSettings()" ng-disabled="state.actionInProgress" button-spinner="state.actionInProgress">
|
|
<span ng-hide="state.actionInProgress">Save settings</span>
|
|
<span ng-show="state.actionInProgress">Saving...</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- !actions -->
|
|
</form>
|
|
</rd-widget-body>
|
|
</rd-widget>
|
|
</div>
|
|
</div>
|