1686 lines
128 KiB
HTML
1686 lines
128 KiB
HTML
{% extends "base.html" %}
|
|
{% set active_page = "admin_settings" %}
|
|
{% block title %}
|
|
<title>Authentication Settings - {{ SITE_NAME }}</title>
|
|
{% endblock %} {% block dashboard_stat %}
|
|
<!-- Content Header (Page header) -->
|
|
<section class="content-header">
|
|
<h1>
|
|
Settings <small>PowerDNS-Admin settings</small>
|
|
</h1>
|
|
<ol class="breadcrumb">
|
|
<li><a href="{{ url_for('dashboard.dashboard') }}"><i class="fa fa-dashboard"></i> Home</a></li>
|
|
<li><a href="#">Setting</a></li>
|
|
<li class="active">Authentication</li>
|
|
</ol>
|
|
<script>
|
|
function ldapSelection() {
|
|
if (document.getElementById('ldap').checked) {
|
|
document.getElementById('ldap_openldap_fields').style.display = 'block';
|
|
document.getElementById('ldap_openldap_group_filters').style.display = 'block';
|
|
document.getElementById('ldap_ad_fields').style.display = 'none';
|
|
} else {
|
|
document.getElementById('ldap_openldap_fields').style.display = 'none';
|
|
document.getElementById('ldap_openldap_group_filters').style.display = 'none';
|
|
document.getElementById('ldap_ad_fields').style.display = 'block';
|
|
}
|
|
}
|
|
|
|
window.onload = function() {
|
|
ldapSelection();
|
|
}
|
|
</script>
|
|
</section>
|
|
{% endblock %}
|
|
{% block content %}
|
|
<section class="content">
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<div class="box box-primary">
|
|
<div class="box-header with-border">
|
|
<h3 class="box-title">Authentication Settings</h3>
|
|
</div>
|
|
<div class="box-body">
|
|
{% if result %}
|
|
<div class="alert {% if result['status'] %}alert-success{% else %}alert-danger{% endif%} alert-dismissible">
|
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
|
{{ result['msg'] }}
|
|
</div>
|
|
{% endif %}
|
|
<!-- Custom Tabs -->
|
|
<div class="nav-tabs-custom" id="tabs">
|
|
<ul class="nav nav-tabs">
|
|
<li class="active"><a href="#tabs-general" data-toggle="tab">General</a></li>
|
|
<li><a href="#tabs-ldap" data-toggle="tab">LDAP</a></li>
|
|
<li><a href="#tabs-google" data-toggle="tab">Google OAuth</a></li>
|
|
<li><a href="#tabs-github" data-toggle="tab">Github OAuth</a></li>
|
|
<li><a href="#tabs-azure" data-toggle="tab">Microsoft OAuth</a></li>
|
|
<li><a href="#tabs-oidc" data-toggle="tab">OpenID Connect OAuth</a></li>
|
|
<li><a href="#tabs-saml" data-toggle="tab">SAML</a></li>
|
|
</ul>
|
|
<div class="tab-content">
|
|
<div class="tab-pane active" id="tabs-general">
|
|
<form role="form" method="post">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="general" name="config_tab" />
|
|
<div class="form-group">
|
|
<input type="checkbox" id="local_db_enabled" name="local_db_enabled" class="checkbox" {% if SETTING.get('local_db_enabled') %}checked{% endif %}>
|
|
<label for="local_db_enabled">Local DB Authentication</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="signup_enabled" name="signup_enabled" class="checkbox" {% if SETTING.get('signup_enabled') %}checked{% endif %}>
|
|
<label for="signup_enabled">Allow users to sign up</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="tabs-ldap">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
{% if error %}
|
|
<div class="alert alert-danger alert-dismissible">
|
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
|
<h4><i class="icon fa fa-ban"></i> Error!</h4>
|
|
{{ error }}
|
|
</div>
|
|
{% endif %}
|
|
<form role="form" method="post" data-toggle="validator">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="ldap" name="config_tab" />
|
|
<fieldset>
|
|
<legend>GENERAL</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="ldap_enabled" name="ldap_enabled" class="checkbox" {% if SETTING.get('ldap_enabled') %}checked{% endif %}>
|
|
<label for="ldap_enabled">Enable LDAP Authentication</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Type</label>
|
|
<div class="radio">
|
|
<label>
|
|
<input type="radio" name="ldap_type" id="ldap" onclick="javascript:ldapSelection();" value="ldap" {% if SETTING.get('ldap_type')=='ldap' %}checked{% endif %}> OpenLDAP
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="ldap_type" id="ad" onclick="javascript:ldapSelection();" value="ad" {% if SETTING.get('ldap_type')=='ad' %}checked{% endif %}> Active Directory
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>ADMINISTRATOR INFO</legend>
|
|
<div class="form-group">
|
|
<label for="ldap_uri">LDAP URI</label>
|
|
<input type="text" class="form-control" name="ldap_uri" id="ldap_uri" placeholder="e.g. ldaps://your-ldap-server:636" data-error="Please input LDAP URI" value="{{ SETTING.get('ldap_uri') }}">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_base_dn">LDAP Base DN</label>
|
|
<input type="text" class="form-control" name="ldap_base_dn" id="ldap_base_dn" placeholder="e.g. dc=mydomain,dc=com" data-error="Please input LDAP Base DN" value="{{ SETTING.get('ldap_base_dn') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div id="ldap_openldap_fields">
|
|
<div class="form-group">
|
|
<label for="ldap_admin_username">LDAP admin username</label>
|
|
<input type="text" class="form-control" name="ldap_admin_username" id="ldap_admin_username" placeholder="e.g. cn=admin,dc=mydomain,dc=com" data-error="Please input LDAP admin username" value="{{ SETTING.get('ldap_admin_username') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_admin_password">LDAP admin password</label>
|
|
<input type="password" class="form-control" name="ldap_admin_password" id="ldap_admin_password" placeholder="LDAP Admin password" data-error="Please input LDAP admin password" value="{{ SETTING.get('ldap_admin_password') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</div>
|
|
<div id="ldap_ad_fields">
|
|
<div class="form-group">
|
|
<label for="ldap_domain">Active Directory domain</label>
|
|
<input type="text" class="form-control" name="ldap_domain" id="ldap_domain" placeholder="Active Directory domain" data-error="Please input Actve Directory domain value" value="{{ SETTING.get('ldap_domain') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>FILTERS</legend>
|
|
<div class="form-group">
|
|
<label for="ldap_filter_basic">Basic filter</label>
|
|
<input type="text" class="form-control" name="ldap_filter_basic" id="ldap_filter_basic" placeholder="e.g. (objectClass=inetorgperson)" data-error="Please input LDAP filter" value="{{ SETTING.get('ldap_filter_basic') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_filter_username">Username field</label>
|
|
<input type="text" class="form-control" name="ldap_filter_username" id="ldap_filter_username" placeholder="e.g. uid" data-error="Please input field for username filtering" value="{{ SETTING.get('ldap_filter_username') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div id="ldap_openldap_group_filters">
|
|
<div class="form-group">
|
|
<label for="ldap_filter_group">Group filter</label>
|
|
<input type="text" class="form-control" name="ldap_filter_group" id="ldap_filter_group" placeholder="e.g. (objectclass=groupOfNames)" data-error="Please input LDAP filter" value="{{ SETTING.get('ldap_filter_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_filter_groupname">Group name field</label>
|
|
<input type="text" class="form-control" name="ldap_filter_groupname" id="ldap_filter_groupname" placeholder="e.g. member" data-error="Please input field for group name filtering" value="{{ SETTING.get('ldap_filter_groupname') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>GROUP SECURITY</legend>
|
|
<div class="form-group">
|
|
<label>Status</label>
|
|
<div class="radio">
|
|
<label>
|
|
<input type="radio" name="ldap_sg_enabled" id="ldap_sg_off" value="OFF" {% if not SETTING.get('ldap_sg_enabled') %}checked{% endif %}> OFF
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="ldap_sg_enabled" id="ldap_sg_on" value="ON" {% if SETTING.get('ldap_sg_enabled') %}checked{% endif %}> ON
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_admin_group">Admin group</label>
|
|
<input type="text" class="form-control" name="ldap_admin_group" id="ldap_admin_group" placeholder="e.g. cn=sysops,dc=mydomain,dc=com" data-error="Please input LDAP DN for Admin group" value="{{ SETTING.get('ldap_admin_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_operator_group">Operator group</label>
|
|
<input type="text" class="form-control" name="ldap_operator_group" id="ldap_operator_group" placeholder="e.g. cn=operators,dc=mydomain,dc=com" data-error="Please input LDAP DN for Operator group" value="{{ SETTING.get('ldap_operator_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ldap_user_group">User group</label>
|
|
<input type="text" class="form-control" name="ldap_user_group" id="ldap_user_group" placeholder="e.g. cn=users,dc=mydomain,dc=com" data-error="Please input LDAP DN for User group" value="{{ SETTING.get('ldap_user_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>ADVANCE</legend>
|
|
<div class="form-group">
|
|
<label>Roles Autoprovisioning</label>
|
|
<div class="radio">
|
|
<label>
|
|
<input type="radio" name="autoprovisioning" id="autoprovisioning_off" value="OFF" {% if not SETTING.get('autoprovisioning') %}checked{% endif %}> OFF
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="autoprovisioning" id="autoprovisioning_on" value="ON"
|
|
|
|
{% if SETTING.get('autoprovisioning') %}checked{% endif %}> ON
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="autoprovisioning_attribute">Roles provisioning field</label>
|
|
<input type="text" class="form-control" name="autoprovisioning_attribute" id="autoprovisioning_attribute" placeholder="e.g. eduPersonEntitlement" data-error=" Please input field responsible for autoprovisioning" value="{{ SETTING.get('autoprovisioning_attribute') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
|
|
<div class="form-group {% if error %}has-error{% endif %}">
|
|
<label for="urn_value">Urn prefix</label>
|
|
<input type="text" class="form-control" name="urn_value" id="urn_value" placeholder="e.g. urn:mace:<yourOrganization>" data-error="Please fill this field" value="{{ SETTING.get('urn_value') }}">
|
|
{% if error %}
|
|
<span class="help-block with-errors">Please input the correct prefix for your urn value</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Purge Roles If Empty</label>
|
|
<div class="radio">
|
|
<label>
|
|
<input type="radio" name="purge" id="purge_off" value="OFF" {% if not SETTING.get('purge') %}checked{% endif %}> OFF
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="purge" id="purge_on" value="ON" {% if SETTING.get('purge') %}checked{% endif %}> ON
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<legend>Help</legend>
|
|
<dl class="dl-horizontal">
|
|
<dt>Enable LDAP Authentication</dt>
|
|
<dd>Turn on / off the LDAP authentication.</dd>
|
|
<dt>Type</dt>
|
|
<dd>Select your current directory service type.
|
|
<ul>
|
|
<li>
|
|
OpenLDAP - Open source implementation of the Lightweight Directory Access Protocol.
|
|
</li>
|
|
<li>
|
|
Active Directory - Active Directory is a directory service that Microsoft developed for the Windows domain networks.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>ADMINISTRATOR INFO</dt>
|
|
<dd>Your LDAP connection string and admin credential used by PDA to query user information.
|
|
<ul>
|
|
<li>
|
|
LDAP URI - The fully qualified domain names of your directory servers. (e.g. ldap://127.0.0.1:389)
|
|
</li>
|
|
<li>
|
|
LDAP Base DN - The point from where a PDA will search for users.
|
|
</li>
|
|
<li>
|
|
LDAP admin username - Your LDAP administrator user which has permission to query information in the Base DN above. Not needed for Active Directory authentication.
|
|
</li>
|
|
<li>
|
|
LDAP admin password - The password of LDAP administrator user. Not needed for Active Directory authentication.
|
|
</li>
|
|
<li>
|
|
Active Directory domain - Active Directory domain used.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>FILTERS</dt>
|
|
<dd>Define how you want to filter your user in LDAP query.
|
|
<ul>
|
|
<li>
|
|
Basic filter - The filter that will be applied to all LDAP query by PDA. (e.g. <i>(objectClass=inetorgperson)</i> for OpenLDAP and <i>(objectClass=organizationalPerson)</i> for Active Directory)
|
|
</li>
|
|
<li>
|
|
Username field - The field PDA will look for user's username. (e.g. <i>uid</i> for OpenLDAP and <i>sAMAccountName</i> for Active Directory)
|
|
</li>
|
|
<li>
|
|
Group filter - The filter that will be applied to all LDAP group queries by PDA. (e.g. <i>(objectClass=groupOfNames)</i> for OpenLDAP)
|
|
</li>
|
|
<li>
|
|
Group name field - The field PDA will look for group names. (e.g. <i>member</i> for OpenLDAP)
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>GROUP SECURITY</dt>
|
|
<dd>User can be assigned to PDA's User or Admin group by matching following LDAP Group.
|
|
<ul>
|
|
<li>
|
|
Status - Turn on / off group security feature.
|
|
</li>
|
|
<li>
|
|
Admin group - Your LDAP admin group.
|
|
</li>
|
|
<li>
|
|
Operator group - Your LDAP operator group.
|
|
</li>
|
|
<li>
|
|
User group - Your LDAP user group.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>ADVANCE</dt>
|
|
<dd> Provision PDA user privileges based on LDAP Object Attributes. Alternative to Group Security Role Management.
|
|
<ul>
|
|
<li>
|
|
Roles Autoprovisioning - If toggled on, the PDA Role and the associations of users found in the local db, will be instantly updated from the LDAP server every time they log in.
|
|
</li>
|
|
<li>
|
|
Roles provisioning field - The attribute in the ldap server populated by the urn values where PDA will look for a new Role and/or new associations to domains/accounts.
|
|
</li>
|
|
<li>
|
|
Urn prefix - The prefix used before the static keyword "powerdns-admin" for your entitlements in the ldap server. Must comply with RFC no.8141.
|
|
</li>
|
|
<li>
|
|
Purge Roles If Empty - If toggled on, ldap entries that have no valid "powerdns-admin" records to their autoprovisioning field, will lose all their associations with any domain or account, also reverting to a User in the process, despite their current role in the local db.<br> If toggled off, in the same scenario they get to keep their existing associations and their current Role.
|
|
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane" id="tabs-google">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<form role="form" method="post" data-toggle="validator">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="google" name="config_tab" />
|
|
<fieldset>
|
|
<legend>GENERAL</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="google_oauth_enabled" name="google_oauth_enabled" class="checkbox" {% if SETTING.get('google_oauth_enabled') %}checked{% endif %}>
|
|
<label for="google_oauth_enabled">Enable Google OAuth</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="google_oauth_client_id">Client ID</label>
|
|
<input type="text" class="form-control" name="google_oauth_client_id" id="google_oauth_client_id" placeholder="Google OAuth client ID" data-error="Please input Client ID" value="{{ SETTING.get('google_oauth_client_id') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="google_oauth_client_secret">Client secret</label>
|
|
<input type="text" class="form-control" name="google_oauth_client_secret" id="google_oauth_client_secret" placeholder="Google OAuth client secret" data-error="Please input Client secret" value="{{ SETTING.get('google_oauth_client_secret') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>ADVANCE</legend>
|
|
<div class="form-group">
|
|
<label for="google_token_url">Token URL</label>
|
|
<input type="text" class="form-control" name="google_token_url" id="google_token_url" placeholder="e.g. https://accounts.google.com/o/oauth2/token" data-error="Please input token URL" value="{{ SETTING.get('google_token_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="google_oauth_scope">Scope</label>
|
|
<input type="text" class="form-control" name="google_oauth_scope" id="google_oauth_scope" placeholder="e.g. email profile" data-error="Please input scope" value="{{ SETTING.get('google_oauth_scope') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="google_authorize_url">Authorize URL</label>
|
|
<input type="text" class="form-control" name="google_authorize_url" id="google_authorize_url" placeholder="e.g. https://accounts.google.com/o/oauth2/auth" data-error="Please input Authorize URL" value="{{ SETTING.get('google_authorize_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="google_base_url">Base URL</label>
|
|
<input type="text" class="form-control" name="google_base_url" id="google_base_url" placeholder="e.g. https://www.googleapis.com/oauth2/v1/" data-error="Please input base URL" value="{{ SETTING.get('google_base_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<legend>Help</legend>
|
|
<p>Fill in all the fields in the left form.</p>
|
|
<p>Make sure you add PDA redirection URI (e.g http://localhost:9191/google/authorized) to your Google App Credentials Restriction.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane" id="tabs-github">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<form role="form" method="post" data-toggle="validator">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="github" name="config_tab" />
|
|
<fieldset>
|
|
<legend>GENERAL</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="github_oauth_enabled" name="github_oauth_enabled" class="checkbox" {% if SETTING.get('github_oauth_enabled') %}checked{% endif %}>
|
|
<label for="github_oauth_enabled">Enable Github OAuth</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="github_oauth_key">Client key</label>
|
|
<input type="text" class="form-control" name="github_oauth_key" id="github_oauth_key" placeholder="Github OAuth client ID" data-error="Please input Client key" value="{{ SETTING.get('github_oauth_key') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="github_oauth_secret">Client secret</label>
|
|
<input type="text" class="form-control" name="github_oauth_secret" id="github_oauth_secret" placeholder="Github OAuth client secret" data-error="Please input Client secret" value="{{ SETTING.get('github_oauth_secret') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>ADVANCE</legend>
|
|
<div class="form-group">
|
|
<label for="github_oauth_scope">Scope</label>
|
|
<input type="text" class="form-control" name="github_oauth_scope" id="github_oauth_scope" placeholder="e.g. email" data-error="Please input scope" value="{{ SETTING.get('github_oauth_scope') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="github_oauth_api_url">API URL</label>
|
|
<input type="text" class="form-control" name="github_oauth_api_url" id="github_oauth_api_url" placeholder="e.g. https://api.github.com/user" data-error="Please input API URL" value="{{ SETTING.get('github_oauth_api_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="github_oauth_token_url">Token URL</label>
|
|
<input type="text" class="form-control" name="github_oauth_token_url" id="github_oauth_token_url" placeholder="e.g. https://github.com/login/oauth/access_token" data-error="Please input Token URL" value="{{ SETTING.get('github_oauth_token_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="github_oauth_authorize_url">Authorize URL</label>
|
|
<input type="text" class="form-control" name="github_oauth_authorize_url" id="github_oauth_authorize_url" placeholder="e.g. https://github.com/login/oauth/authorize" data-error="Plesae input Authorize URL" value="{{ SETTING.get('github_oauth_authorize_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<legend>Help</legend>
|
|
<p>Fill in all the fields in the left form.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane" id="tabs-azure">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<form role="form" method="post" data-toggle="validator">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="azure" name="config_tab" />
|
|
<fieldset>
|
|
<legend>GENERAL</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="azure_oauth_enabled" name="azure_oauth_enabled" class="checkbox" {% if SETTING.get('azure_oauth_enabled') %}checked{% endif %}>
|
|
<label for="azure_oauth_enabled">Enable Microsoft Azure OAuth</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_oauth_key">Client key</label>
|
|
<input type="text" class="form-control" name="azure_oauth_key" id="azure_oauth_key" placeholder="Azure OAuth client ID" data-error="Please input Client key" value="{{ SETTING.get('azure_oauth_key') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_oauth_secret">Client secret</label>
|
|
<input type="text" class="form-control" name="azure_oauth_secret" id="azure_oauth_secret" placeholder="Azure OAuth client secret" data-error="Please input Client secret" value="{{ SETTING.get('azure_oauth_secret') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>ADVANCED</legend>
|
|
<div class="form-group">
|
|
<label for="azure_oauth_scope">Scope</label>
|
|
<input type="text" class="form-control" name="azure_oauth_scope" id="azure_oauth_scope" placeholder="e.g. email" data-error="Please input scope - e.g. User.Read" value="{{ SETTING.get('azure_oauth_scope') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_oauth_api_url">API URL</label>
|
|
<input type="text" class="form-control" name="azure_oauth_api_url" id="azure_oauth_api_url" placeholder="e.g. https://graph.microsoft.com/v1.0/" data-error="Please input API URL" value="{{ SETTING.get('azure_oauth_api_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_oauth_token_url">Token URL</label>
|
|
<input type="text" class="form-control" name="azure_oauth_token_url" id="azure_oauth_token_url" placeholder="e.g. https://login.microsoftonline.com/[tenancyID]/oauth2/v2.0/token" data-error="Please input Token URL" value="{{ SETTING.get('azure_oauth_token_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_oauth_authorize_url">Authorize URL</label>
|
|
<input type="text" class="form-control" name="azure_oauth_authorize_url" id="azure_oauth_authorize_url" placeholder="e.g. https://login.microsoftonline.com/[tenancyID]/oauth2/v2.0/authorize" data-error="Please input Authorize URL" value="{{ SETTING.get('azure_oauth_authorize_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>GROUP SECURITY</legend>
|
|
<div class="form-group">
|
|
<label>Status</label>
|
|
<div class="radio">
|
|
<label>
|
|
<input type="radio" name="azure_sg_enabled" id="azure_sg_off" value="OFF" {% if not SETTING.get('azure_sg_enabled') %}checked{% endif %}> OFF
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="azure_sg_enabled" id="azure_sg_on" value="ON" {% if SETTING.get('azure_sg_enabled') %}checked{% endif %}> ON
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_admin_group">Admin group</label>
|
|
<input type="text" class="form-control" name="azure_admin_group" id="azure_admin_group" placeholder="e.g. 00000000-0000-0000-0000-000000000000" data-error="Please input the ID for Admin group" value="{{ SETTING.get('azure_admin_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_operator_group">Operator group</label>
|
|
<input type="text" class="form-control" name="azure_operator_group" id="azure_operator_group" placeholder="e.g. 00000000-0000-0000-0000-000000000000" data-error="Please input the ID for Operator group" value="{{ SETTING.get('azure_operator_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_user_group">User group</label>
|
|
<input type="text" class="form-control" name="azure_user_group" id="azure_user_group" placeholder="e.g. 00000000-0000-0000-0000-000000000000" data-error="Please input the ID for User group" value="{{ SETTING.get('azure_user_group') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>AZURE GROUP ACCOUNT SYNC/CREATION</legend>
|
|
<div class="form-group">
|
|
<label for="azure_group_accounts_enabled">Status</label>
|
|
<div class="radio">
|
|
<label>
|
|
<input type="radio" name="azure_group_accounts_enabled" id="azure_group_accounts_off" value="OFF" {% if not SETTING.get('azure_group_accounts_enabled') %}checked{% endif %}> OFF
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="azure_group_accounts_enabled" id="azure_group_accounts_on" value="ON" {% if SETTING.get('azure_group_accounts_enabled') %}checked{% endif %}> ON
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_group_accounts_name">Azure group name claim</label>
|
|
<input type="text" class="form-control" name="azure_group_accounts_name" id="azure_group_accounts_name" placeholder="e.g. displayName" data-error="Please input the Claim for Azure group name" value="{{ SETTING.get('azure_group_accounts_name') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_group_accounts_name_re">Azure group name claim regex</label>
|
|
<input type="text" class="form-control" name="azure_group_accounts_name_re" id="azure_group_accounts_name_re" placeholder="e.g. (.*)" data-error="Please input the regex for Azure group name" value="{{ SETTING.get('azure_group_accounts_name_re') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_group_accounts_description">Azure group description claim</label>
|
|
<input type="text" class="form-control" name="azure_group_accounts_description" id="azure_group_accounts_description" placeholder="e.g. description. If empty uses whole string" data-error="Please input the Claim for Azure group description" value="{{ SETTING.get('azure_group_accounts_description') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="azure_group_accounts_name_re">Azure group name description regex</label>
|
|
<input type="text" class="form-control" name="azure_group_accounts_description_re" id="azure_group_accounts_description_re" placeholder="e.g. (.*). If empty uses whole string" data-error="Please input the regex for Azure group description" value="{{ SETTING.get('azure_group_accounts_description_re') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<legend>Help</legend>
|
|
<p>Fill in all the fields in the left form.</p>
|
|
<p>You first need to define an Application Registration in your Azure Active Directory, with the appropriate HTTPS URL for this endpoint, and with the appropriate rights, as explained in the documentation.</p>
|
|
<p><ul>
|
|
<li>Under the Azure Active Directory, select App Registrations, and create a new one. Give it any name you want, and the Redirect URI shoule be type 'Web' and of the format <b>https://powerdnsadmin/azure/authorized</b> (replace the host name approriately).</li>
|
|
<li>Select the newly-created registration</li>
|
|
<li>On the Overview page, the Application ID is your new Client ID to use with PowerDNS-Admin</li>
|
|
<li>On the Overview page, make a note of your Directory/Tenant ID - you need it for the API URLs later</li>
|
|
<li>Ensure Access Tokens are enabled in the Authentication section</li>
|
|
<li>Under Certificates and Secrets, create a new Client Secret. Note this secret as it is the new Client Secret to use with PowerDNS-Admin</li>
|
|
<li>Under API Permissions, you need to add permissions. Add permissions for Graph API, Delegated. Add: email, openid, profile, GroupMember.Read, User.Read and possibly User.Read.All. You then need to grant admin approval for your organisation.</li>
|
|
<li>For the Scope, use <b>User.Read openid mail profile</b></li>
|
|
<li>Replace the [tenantID] in the default URLs for authorize and token with your Tenant ID.</li>
|
|
</ul></p>
|
|
<p>If <b>AZURE GROUP ACCOUNT SYNC/CREATION</b> is enabled, Accounts will be created automatically based on group membership. If an Account exists, an authenticated user with group membership is added to the Account</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane" id="tabs-oidc">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<form role="form" method="post" data-toggle="validator">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="oidc" name="config_tab" />
|
|
<fieldset>
|
|
<legend>GENERAL</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="oidc_oauth_enabled" name="oidc_oauth_enabled" class="checkbox" {% if SETTING.get('oidc_oauth_enabled') %}checked{% endif %}>
|
|
<label for="oidc_oauth_enabled">Enable OpenID Connect OAuth</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_key">Client key</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_key" id="oidc_oauth_key" placeholder="OIDC OAuth client ID" data-error="Please input Client key" value="{{ SETTING.get('oidc_oauth_key') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_secret">Client secret</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_secret" id="oidc_oauth_secret" placeholder="OIDC OAuth client secret" data-error="Please input Client secret" value="{{ SETTING.get('oidc_oauth_secret') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_scope">Scope</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_scope" id="oidc_oauth_scope" placeholder="e.g. email" data-error="Please input scope" value="{{ SETTING.get('oidc_oauth_scope') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_api_url">API URL</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_api_url" id="oidc_oauth_api_url" placeholder="e.g. https://api.oidc.com/user" data-error="Please input API URL" value="{{ SETTING.get('oidc_oauth_api_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_token_url">Token URL</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_token_url" id="oidc_oauth_token_url" placeholder="e.g. https://oidc.com/login/oauth/access_token" data-error="Please input Token URL" value="{{ SETTING.get('oidc_oauth_token_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_authorize_url">Authorize URL</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_authorize_url" id="oidc_oauth_authorize_url" placeholder="e.g. https://oidc.com/login/oauth/authorize" data-error="Plesae input Authorize URL" value="{{ SETTING.get('oidc_oauth_authorize_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_logout_url">Logout URL</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_logout_url" id="oidc_oauth_logout_url" placeholder="e.g. https://oidc.com/login/oauth/logout" data-error="Please input Logout URL" value="{{ SETTING.get('oidc_oauth_logout_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>CLAIMS</legend>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_username">Username</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_username" id="oidc_oauth_username" placeholder="e.g. preferred_username" data-error="Please input Username claim" value="{{ SETTING.get('oidc_oauth_username') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_firstname">First Name</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_firstname" id="oidc_oauth_firstname" placeholder="e.g. given_name" data-error="Please input First Name claim" value="{{ SETTING.get('oidc_oauth_firstname') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_last_name">Last Name</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_last_name" id="oidc_oauth_last_name" placeholder="e.g. family_name" data-error="Please input Last Name claim" value="{{ SETTING.get('oidc_oauth_last_name') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_email">Email</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_email" id="oidc_oauth_email" placeholder="e.g. email" data-error="Plesae input Email claim" value="{{ SETTING.get('oidc_oauth_email') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>ADVANCE</legend>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_account_name_property">Autoprovision Account Name property</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_account_name_property" id="oidc_oauth_account_name_property" placeholder="e.g. account_name" data-error="Please input property containing account_name" value="{{ SETTING.get('oidc_oauth_account_name_property') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="oidc_oauth_account_description_property">Autoprovision Account Description property</label>
|
|
<input type="text" class="form-control" name="oidc_oauth_account_description_property" id="oidc_oauth_account_description_property" placeholder="e.g. account_description" data-error="Please input property containing account_description" value="{{ SETTING.get('oidc_oauth_account_description_property') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<legend>Help</legend>
|
|
<p>Fill in all the fields in the left form.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane" id="tabs-saml">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<form role="form" method="post" data-toggle="validator">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" value="saml" name="config_tab" />
|
|
<fieldset>
|
|
<legend>GENERAL</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_enabled" name="saml_enabled" class="checkbox" {% if SETTING.get('saml_enabled') %}checked{% endif %}>
|
|
<label for="saml_enabled">Enable SAML</label>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>IDP</legend>
|
|
<div class="form-group">
|
|
<label for="saml_idp_entity_id">IDP Entity ID</label>
|
|
<input type="text" class="form-control" name="saml_idp_entity_id" id="saml_idp_entity_id" placeholder="e.g. https://idp.example.edu/idp" data-error="Please input SAML IDP Entity ID" value="{{ SETTING.get('saml_idp_entity_id') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_metadata_url">IDP Metadata URL</label>
|
|
<input type="text" class="form-control" name="saml_metadata_url" id="saml_metadata_url" placeholder="SAML Metadata URL" data-error="Please input SAML Metadata URL" value="{{ SETTING.get('saml_metadata_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_metadata_cache_lifetime">IDP Metadata Cache Lifetime</label>
|
|
<input type="text" class="form-control" name="saml_metadata_cache_lifetime" id="saml_metadata_cache_lifetime" placeholder="SAML Metadata Cache Lifetime" data-error="Please input SAML Metadata Cache Lifetime" value="{{ SETTING.get('saml_metadata_cache_lifetime') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_idp_sso_binding">IDP SSO Binding</label>
|
|
<input type="text" class="form-control" name="saml_idp_sso_binding" id="saml_idp_sso_binding" placeholder="e.g. urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" data-error="Please input SAML IDP SSO Binding" value="{{ SETTING.get('saml_idp_sso_binding') }}" readonly>
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_idp_slo_binding">IDP SLO Binding</label>
|
|
<input type="text" class="form-control" name="saml_idp_slo_binding" id="saml_idp_slo_binding" placeholder="e.g. urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" data-error="Please input SAML IDP SLO Binding" value="{{ SETTING.get('saml_idp_slo_binding') }}" readonly>
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>SP</legend>
|
|
<div class="form-group">
|
|
<label for="saml_sp_entity_id">SP Entity ID</label>
|
|
<input type="text" class="form-control" name="saml_sp_entity_id" id="saml_sp_entity_id" placeholder="http://<SAML SP Entity ID>" data-error="Please input SAML SP Entity ID" value="{{ SETTING.get('saml_sp_entity_id') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_nameid_format">SP NameID Format</label>
|
|
<input type="text" class="form-control" name="saml_nameid_format" id="saml_nameid_format" placeholder="e.g. urn:oid:0.9.2342.19200300.100.1.1" data-error="Please input NameID Format" value="{{ SETTING.get('saml_nameid_format') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_metadata_cache_duration">SP Metadata Cache Duration</label>
|
|
<input type="text" class="form-control" name="saml_metadata_cache_duration" id="saml_metadata_cache_duration" placeholder="eg PT5M" data-error="Please input Metadata Cache Duration" value="{{ SETTING.get('saml_metadata_cache_duration') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_metadata_valid_until">SP Metadata Valid Until</label>
|
|
<input type="text" class="form-control" name="saml_metadata_valid_until" id="saml_metadata_valid_until" placeholder="YYYY-MM-DDThh:mm:ssZ" data-error="Please input Metadata Expiration Date" value="{{ SETTING.get('saml_metadata_valid_until') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_sign_metadata" name="saml_sign_metadata" class="checkbox" {% if SETTING.get('saml_sign_metadata') %}checked{% endif %}>
|
|
<label for="saml_sign_metadata">Sign SP Metadata </label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_sp_acs_binding">SP ACS Binding</label>
|
|
<input type="text" class="form-control" name="saml_sp_acs_binding" id="saml_sp_acs_binding" placeholder="e.g. urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" data-error="Please input SAML SP ACS Binding" value="{{ SETTING.get('saml_sp_acs_binding') }}" readonly>
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_sp_acs_binding">SP SLS Binding</label>
|
|
<input type="text" class="form-control" name="saml_sp_sls_binding" id="saml_sp_sls_binding" placeholder="e.g. urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" data-error="Please input SAML SP SLS Binding" value="{{ SETTING.get('saml_sp_sls_binding') }}" readonly>
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>SP ATTRIBUTES</legend>
|
|
<div class="form-group">
|
|
<label for="saml_sp_requested_attributes">Requested Attributes</label>
|
|
<input type="text" class="form-control" name="saml_sp_requested_attributes" id="saml_sp_requested_attributes" placeholder="must be valid JSON" data-error="Plesae input Requested Attributes" value="{{ SETTING.get('saml_sp_requested_attributes') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_attribute_email">Email</label>
|
|
<input type="text" class="form-control" name="saml_attribute_email" id="saml_attribute_email" placeholder="e.g. urn:oid:0.9.2342.19200300.100.1.3" data-error="Please input SAML Email Attribute" value="{{ SETTING.get('saml_attribute_email') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_attribute_givenname">Given Name</label>
|
|
<input type="text" class="form-control" name="saml_attribute_givenname" id="saml_attribute_givenname" placeholder="e.g. urn:oid:2.5.4.42" data-error="Please input SAML Given Name Attribute" value="{{ SETTING.get('saml_attribute_givenname') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_attribute_surname">Surname</label>
|
|
<input type="text" class="form-control" name="saml_attribute_surname" id="saml_attribute_surname" placeholder="e.g. urn:oid:2.5.4.4" data-error="Please input SAML Surname Attribute" value="{{ SETTING.get('saml_attribute_surname') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_attribute_username">Username</label>
|
|
<input type="text" class="form-control" name="saml_attribute_username" id="saml_attribute_username" placeholder="e.g. urn:oid:0.9.2342.19200300.100.1.1" data-error="Please input SAML Username Attribute" value="{{ SETTING.get('saml_attribute_username') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_sp_contact_name">SP Contact Name</label>
|
|
<input type="text" class="form-control" name="saml_sp_contact_name" id="saml_sp_contact_name" placeholder="<contact name>" data-error="Please input SAML SP contact name" value="{{ SETTING.get('saml_sp_contact_name') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_sp_contact_mail">SP Contact Mail</label>
|
|
<input type="text" class="form-control" name="saml_sp_contact_mail" id="saml_sp_contact_mail" placeholder="<contact mail>" data-error="Please input SAML SP contact mail" value="{{ SETTING.get('saml_sp_contact_mail') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>SIGNING & ENCRYPTION</legend>
|
|
<div class="form-group">
|
|
<label for="saml_cert_file">Cert File</label>
|
|
<input type="text" class="form-control" name="saml_cert_file" id="saml_cert_file" placeholder="e.g. opt/web/PowerDNS-Admin/cert.crt" data-error="Please input SAML cert file path" value="{{ SETTING.get('saml_cert_file') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_cert_key">Cert Key</label>
|
|
<input type="text" class="form-control" name="saml_cert_key" id="saml_cert_key" placeholder="e.g. opt/web/PowerDNS-Admin/key.pem" data-error="Please input SAML key file path" value="{{ SETTING.get('saml_cert_key') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_sign_authn_request" name="saml_sign_authn_request" class="checkbox" {% if SETTING.get('saml_sign_authn_request') %}checked{% endif %}>
|
|
<label for="saml_sign_authn_request">Sign Authentication Request</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_sign_logout_request_response" name="saml_sign_logout_request_response" class="checkbox" {% if SETTING.get('saml_sign_logout_request_response') %}checked{% endif %}>
|
|
<label for="saml_sign_logout_request_response">Sign Logout Request & Response</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_want_assertions_encrypted" name="saml_want_assertions_encrypted" class="checkbox" {% if SETTING.get('saml_want_assertions_encrypted') %}checked{% endif %}>
|
|
<label for="saml_want_assertions_encrypted">Want Assertions Encrypted</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_want_assertions_signed" name="saml_want_assertions_signed" class="checkbox" {% if SETTING.get('saml_want_assertions_signed') %}checked{% endif %}>
|
|
<label for="saml_want_assertions_signed">Want Assertions Signed</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_want_message_signed" name="saml_want_message_signed" class="checkbox" {% if SETTING.get('saml_want_message_signed') %}checked{% endif %}>
|
|
<label for="saml_want_message_signed">Want Message Signed </label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_nameid_encrypted" name="saml_nameid_encrypted" class="checkbox" {% if SETTING.get('saml_nameid_encrypted') %}checked{% endif %}>
|
|
<label for="saml_nameid_encrypted">NameID Encrypted</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_want_nameid_encrypted" name="saml_want_nameid_encrypted" class="checkbox" {% if SETTING.get('saml_want_nameid_encrypted') %}checked{% endif %}>
|
|
<label for="saml_want_nameid_encrypted">Want NameID Encrypted</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_digest_algorithm">Digest Algorithm</label>
|
|
<input type="text" class="form-control" name="saml_digest_algorithm" id="saml_digest_algorithm" placeholder="must be a valid algorithm" data-error="Please input SAML digest algorithm" value="{{ SETTING.get('saml_digest_algorithm') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_signature_algorithm">Signature Algorithm</label>
|
|
<input type="text" class="form-control" name="saml_signature_algorithm" id="saml_signature_algorithm" placeholder="must be a valid algorithm" data-error="Please input SAML signature algorithm" value="{{ SETTING.get('saml_signature_algorithm') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>LOGOUT</legend>
|
|
<div class="form-group">
|
|
<input type="checkbox" id="saml_logout" name="saml_logout" class="checkbox" {% if SETTING.get('saml_logout') %}checked{% endif %}>
|
|
<label for="saml_logout">SAML Logout</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_logout_url">Logout URL</label>
|
|
<input type="text" class="form-control" name="saml_logout_url" id="saml_logout_url" placeholder="must be a valid logout URL" data-error="Please input SAML logout URL" value="{{ SETTING.get('saml_logout_url') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>AUTOPROVISION</legend>
|
|
<div class="form-group">
|
|
<label for="saml_attribute_admin">Admin SP Attribute</label>
|
|
<input type="text" class="form-control" name="saml_attribute_admin" id="saml_attribute_admin" placeholder="e.g. https://example.edu/pdns-admin" data-error="Please input SAML Admin Attribute" value="{{ SETTING.get('saml_attribute_admin') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="saml_attribute_account">Account SP Attribute</label>
|
|
<input type="text" class="form-control" name="saml_attribute_account" id="saml_attribute_account" placeholder="e.g. https://example.edu/pdns-account" data-error="Please input SAML Account Attribute" value="{{ SETTING.get('saml_attribute_account') }}">
|
|
<span class="help-block with-errors"></span>
|
|
</div>
|
|
</fieldset>
|
|
<div class="form-group">
|
|
<button type="submit" class="btn btn-flat btn-primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<legend>Help</legend>
|
|
<dl class="dl-horizontal">
|
|
<dt>General</dt>
|
|
<dd> <br>
|
|
<b>Enable SAML</b> - Enables or disables SAML Authentication. <br>
|
|
If toggled on, the following fields must be filled in the left form:
|
|
<ul>
|
|
<li>
|
|
<b>IDP Entity ID</b>
|
|
</li>
|
|
<li>
|
|
<b>IDP Metadata URL</b>
|
|
</li>
|
|
<li>
|
|
<b>SP Entity ID</b>
|
|
</li>
|
|
<li>
|
|
<b>SP NameID Format</b>
|
|
</li>
|
|
<li>
|
|
<b>SP Requested Attributes</b>
|
|
</li>
|
|
<li>
|
|
<b>SP Username Attribute</b>
|
|
</li>
|
|
<li>
|
|
<b>Cert File</b>
|
|
</li>
|
|
<li>
|
|
<b>Cert Key</b>
|
|
</li>
|
|
<li>
|
|
<b>Digest Algorithm</b>
|
|
</li>
|
|
<li>
|
|
<b>Signature Algorithm</b>
|
|
</li>
|
|
<li>
|
|
<b>Logout URL</b>, if <i>SAML Logout</i> is toggled on
|
|
</li>
|
|
<li>
|
|
<b>Roles Provisioning Field</b> and <b>Urn Prefix</b>, if <i>Roles Autoprovisioning</i> is toggled on.
|
|
</li>
|
|
</ul>
|
|
The rest can be filled, or left empty to revert to the Default settings.
|
|
</dd>
|
|
<dt>IDP</dt>
|
|
<dd> <br>
|
|
<ul>
|
|
<li>
|
|
<b>IDP Entity ID</b> - Specify the EntityID of the IDP to use.<br>
|
|
Only needed if more the XML provided in the SAML_METADATA_URL contains more than 1 IDP Entity.
|
|
</li>
|
|
<li>
|
|
<b>IDP Metadata URL</b> - Url where the XML of the Identity Provider Metadata is published.
|
|
</li>
|
|
<li>
|
|
<b>IDP Metadata Cache Lifetime</b> - Cache Lifetime in minutes before fresh metadata are fetched from the IDP Metadata URL
|
|
</li>
|
|
<li>
|
|
<b>IDP SSO Binding</b> - SAML SSO binding format required for the IDP to use<br>
|
|
</li>
|
|
<li>
|
|
<b>IDP SLO Binding</b> - SAML SLO binding format required for the IDP to use<br>
|
|
</li>
|
|
<b>NOTE:</b>:The Binding settings are currently disabled, as the underlying saml library currently supports only the Redirect binding for IDP endpoints.<br>
|
|
</ul>
|
|
</dd>
|
|
<dt>SP</dt>
|
|
<dd> <br>
|
|
<ul>
|
|
<li>
|
|
<b>SP Entity ID</b> - Specify the EntityID of your Service Provider (SP).
|
|
</li>
|
|
<li>
|
|
<b>SP NameID Format</b> - NameID format to request. This specifies the content of the NameID and any associated processing rules.
|
|
</li>
|
|
<li>
|
|
<b>SP Metadata Cache Duration</b> - Set the cache duration of generated metadata.<br>
|
|
Use PT5M to set cache duration to 5 minutes.
|
|
</li>
|
|
<li>
|
|
<b>SP Metadata Valid Until</b> - Set the expiration date, in XML DateTime String format, for generated metadata.<br>
|
|
XML DateTime String Format: "YYYY-MM-DDThh:mm:ssZ", Z can be Z for timezone 0 or "+-hh:mm" for other timezones.
|
|
</li>
|
|
<li>
|
|
<b>Sign SP Metadata</b> - Choose whether metadata produced is signed.
|
|
</li>
|
|
<li>
|
|
<b>SP ACS Binding</b> - SAML Assertion Consumer Service Binding Format for the SP to use on login.
|
|
</li>
|
|
<li>
|
|
<b>SP SLS Binding</b> - SAML Single Logout Service Binding Format for the SP to use on logout.
|
|
</li>
|
|
<b>NOTE:</b>:The Binding settings are currently disabled, as in the underlying saml library, the ACS endpoint currently supports
|
|
only the HTTP-POST binding, while the SLS endpoint supports only HTTP-Redirect.
|
|
</ul>
|
|
</dd>
|
|
<dt>SP ATTRIBUTES</dt>
|
|
<dd> <br>
|
|
<ul>
|
|
<li>
|
|
<b>Requested Attributes</b> - The following parameter defines RequestedAttributes section in SAML metadata
|
|
since certain IDPs require explicitly requesting attributes.<br>
|
|
If not provided, the Attribute Consuming Service Section will not be available in metadata.
|
|
<br>
|
|
<u>Possible attributes</u>:<br>
|
|
<i>name (mandatory), nameFormat, isRequired, friendlyName</i>
|
|
<br>
|
|
<b>NOTE:</b> This parameter requires to be entered in valid JSON format as displayed below
|
|
and multiple attributes can be given.
|
|
<br>
|
|
Following <i>example</i>:
|
|
<br>
|
|
<code>SAML_SP_REQUESTED_ATTRIBUTES = '[ <br>
|
|
{"name": "urn:oid:0.9.2342.19200300.100.1.3", "nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "isRequired": true, "friendlyName": "email"}, <br>
|
|
{"name": "mail", "isRequired": false, "friendlyName": "test-field"} <br>
|
|
]'</code>
|
|
<br>
|
|
produces following <i>metadata section</i>:
|
|
<br><code>
|
|
<md:AttributeConsumingService index="1"><br>
|
|
<md:RequestedAttribute Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="email" isRequired="true"/><br>
|
|
<md:RequestedAttribute Name="mail" FriendlyName="test-field"/><br>
|
|
</md:AttributeConsumingService></code>
|
|
</li>
|
|
</ul>
|
|
The following attribute values must be <i>derived</i> from <b>Requested Attributes</b>, and must be in the form of a <b>valid URN</b> (e.g. <i>urn:oid:2.5.4.4</i>):
|
|
<ul>
|
|
<li>
|
|
<b>Email</b> - Attribute to use for Email address.
|
|
</li>
|
|
<li>
|
|
<b>Given Name</b> - Attribute to use for Given name.
|
|
</li>
|
|
<li>
|
|
<b>Surname</b> - Attribute to use for Surname.
|
|
</li>
|
|
<li>
|
|
<b>Username</b> - Attribute to use for username.
|
|
</li>
|
|
</ul>
|
|
These may be generic strings containing your information:
|
|
<ul>
|
|
<li>
|
|
<b>SP Entity Name</b> - Contact information about your SP, to be included in the generated metadata.
|
|
</li>
|
|
<li>
|
|
<b>SP Entity Mail</b> - Contact information about your SP, to be included in the generated metadata.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>ENCRYPTION</dt>
|
|
<dd> <br>
|
|
<ul>
|
|
<li>
|
|
The <b>Cert File</b> - <b>Cert Key</b> pair configures the path
|
|
to certificate file and it's respective private key file.<br>
|
|
It is used for signing metadata, encrypting tokens and all other
|
|
signing/encryption tasks during communication between IDP and SP.<br>
|
|
<b>NOTE</b>: If these two parameters aren't explicitly provided,
|
|
a self-signed certificate-key pair will be generated.<br>
|
|
</li>
|
|
<li>
|
|
<b>Sign Authentication Request</b> - Configures if the SP should sign <b>outgoing</b> authentication requests.
|
|
</li>
|
|
<li>
|
|
<b>Sign Logout Request & Response</b> - Configures if the SP should sign <b>outgoing</b> Logout requests & Logout responses.
|
|
</li>
|
|
<li>
|
|
<b>Want Assertions Encrypted</b> - Choose whether the SP expects <b>incoming</b> assertions received from the IDP to be encrypted.
|
|
</li>
|
|
<li>
|
|
<b>Want Assertions Signed</b> - Choose whether the SP expects <b>incoming</b> assertions to be signed.
|
|
</li>
|
|
<li>
|
|
<b>NameID Encrypted</b> - Indicates that the <b>outgoing</b> nameID of the logoutRequest sent by this SP will be encrypted.
|
|
</li>
|
|
<li>
|
|
<b>Want NameID Encrypted</b> - Indicates a requirement for the <b>incoming</b> NameID received by this SP to be encrypted.
|
|
</li>
|
|
<li>
|
|
<b>Want Message Signed</b> - Choose whether the SP expects <b>incoming</b> messages to be signed.
|
|
</li>
|
|
<li>
|
|
<b>Digest Algorithm</b> - Encryption algorithm for the DigestValue, which is part of the validation process to ensure the integrity of the XML message.
|
|
</li>
|
|
<li>
|
|
<b>Signature Algorithm</b> - Encryption algorithm for the message Signature.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>LOGOUT</dt>
|
|
<dd> <br>
|
|
<ul>
|
|
<li>
|
|
<b>SAML Logout</b> - Choose whether user is logged out of the SAML session using SLO.
|
|
<ul>
|
|
<li>
|
|
If enabled, use SAML standard logout mechanism retreived from IDP metadata.
|
|
</li>
|
|
<li>
|
|
If disabled, don't care about SAML session on logout.<br>
|
|
Logout from PowerDNS-Admin only and keep SAML session authenticated.
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li>
|
|
<b>Logout URL</b> - Configure to redirect to a url different than PowerDNS-Admin login after a successful SAML logout.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
<dt>AUTOPROVISION</dt>
|
|
<dd> <br>
|
|
Assert user Admin status and associated Accounts with SAML Attributes.
|
|
<ul>
|
|
<li>
|
|
<b>Admin</b> - Attribute to get admin status from.<br>
|
|
If set, look for the value 'true' to set a user as an administrator.<br>
|
|
If not included in assertion, or set to something other than 'true',
|
|
the user is set as a non-administrator user.
|
|
</li>
|
|
<li>
|
|
<b>Account</b> - Attribute to get account names from.<br>
|
|
If set, the user will be added and removed from accounts to match
|
|
what's in the login assertion.<br>Accounts that don't exist will
|
|
be created and the user added to them.
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{% endblock %}
|
|
{% block extrascripts %}
|
|
{% assets "js_validation" -%}
|
|
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
|
|
{%- endassets %}
|
|
|
|
<script>
|
|
|
|
$(document).ready(function() {
|
|
// Focus on text attribute of modal
|
|
$("#modal_requested_attributes").on('shown.bs.modal', function() {
|
|
$("#txt_req_attr").focus();
|
|
});
|
|
});
|
|
|
|
$(function() {
|
|
$('#tabs').tabs({
|
|
// add url anchor tags
|
|
activate: function(event, ui) {
|
|
window.location.hash = ui.newPanel.attr('id');
|
|
}
|
|
});
|
|
// re-set active tab (ui)
|
|
var activeTabIdx = $('#tabs').tabs('option','active');
|
|
$('#tabs li:eq('+activeTabIdx+')').tab('show')
|
|
});
|
|
|
|
// START: General tab js
|
|
$('#local_db_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
|
|
$('#signup_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
|
|
$('#autoprovisioning').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
// END: General tab js
|
|
|
|
// START: LDAP tab js
|
|
// update validation requirement when checkbox is togged
|
|
$('#ldap_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#ldap_uri').prop('required', true);
|
|
$('#ldap_base_dn').prop('required', true);
|
|
if ($('#ldap').is(":checked") ) {
|
|
$('#ldap_admin_username').prop('required', true);
|
|
$('#ldap_admin_password').prop('required', true);
|
|
$('#ldap_domain').prop('required', false);
|
|
} else {
|
|
$('#ldap_admin_username').prop('required', false);
|
|
$('#ldap_admin_password').prop('required', false);
|
|
$('#ldap_domain').prop('required', true);
|
|
}
|
|
$('#ldap_filter_basic').prop('required', true);
|
|
$('#ldap_filter_group').prop('required', true);
|
|
$('#ldap_filter_username').prop('required', true);
|
|
$('#ldap_filter_groupname').prop('required', true);
|
|
|
|
if ($('#ldap_sg_on').is(":checked")) {
|
|
$('#ldap_admin_group').prop('required', true);
|
|
$('#ldap_operator_group').prop('required', true);
|
|
$('#ldap_user_group').prop('required', true);
|
|
}
|
|
if ($('#autoprovisioning').is(":checked")) {
|
|
$('#autoprovisioning_attribute').prop('required', true);
|
|
$('#urn_value').prop('required', true);
|
|
}
|
|
} else {
|
|
$('#ldap_uri').prop('required', false);
|
|
$('#ldap_base_dn').prop('required', false);
|
|
$('#ldap_admin_username').prop('required', false);
|
|
$('#ldap_admin_password').prop('required', false);
|
|
$('#ldap_filter_basic').prop('required', false);
|
|
$('#ldap_filter_group').prop('required', false);
|
|
$('#ldap_filter_username').prop('required', false);
|
|
$('#ldap_filter_groupname').prop('required', false);
|
|
|
|
if ($('#ldap_sg_on').is(":checked")) {
|
|
$('#ldap_admin_group').prop('required', false);
|
|
$('#ldap_operator_group').prop('required', false);
|
|
$('#ldap_user_group').prop('required', false);
|
|
}
|
|
if ($('#autoprovisioning').is(":checked")) {
|
|
$('#autoprovisioning_attribute').prop('required', false);
|
|
$('#urn_value').prop('required', true);
|
|
}
|
|
}
|
|
});
|
|
|
|
$("input[name='ldap_sg_enabled']" ).change(function(){
|
|
if ($('#ldap_sg_on').is(":checked") && $('#ldap_enabled').is(":checked")) {
|
|
$('#ldap_admin_group').prop('required', true);
|
|
$('#ldap_operator_group').prop('required', true);
|
|
$('#ldap_user_group').prop('required', true);
|
|
} else {
|
|
$('#ldap_admin_group').prop('required', false);
|
|
$('#ldap_operator_group').prop('required', false);
|
|
$('#ldap_user_group').prop('required', false);
|
|
}
|
|
|
|
if ($('#ldap_sg_on').is(":checked") && $('#autoprovisioning_on').is(":checked")){
|
|
document.getElementById('ldap_sg_on').checked=false;
|
|
document.getElementById('ldap_sg_off').checked=true;
|
|
var modal = $("#modal_warning");
|
|
|
|
var info = "Group Security:Status and Advance:Autoprovisioning can not be both enabled at the same time. Please turn off Advance:Autoprovisioning first" ;
|
|
modal.find('.modal-body p').text(info);
|
|
modal.find('#button_warning_confirm').click(function () {
|
|
modal.modal('hide');
|
|
})
|
|
modal.find('#warning_X').click(function () {
|
|
modal.modal('hide');
|
|
})
|
|
modal.modal('show');
|
|
}
|
|
});
|
|
|
|
$("input[name='autoprovisioning']" ).change(function(){
|
|
if ($('#autoprovisioning_on').is(":checked") && $('#ldap_enabled').is(":checked")) {
|
|
$('#autoprovisioning_attribute').prop('required', true);
|
|
$('#urn_value').prop('required', true);
|
|
$('#purge').prop('required', true);
|
|
}
|
|
else{
|
|
$('#autoprovisioning_attribute').prop('required', false);
|
|
$('#urn_value').prop('required', false);
|
|
$('#purge').prop('required', false);
|
|
}
|
|
if ($('#ldap_sg_on').is(":checked") && $('#autoprovisioning_on').is(":checked")){
|
|
document.getElementById('autoprovisioning_on').checked=false;
|
|
document.getElementById('autoprovisioning_off').checked=true;
|
|
var modal = $("#modal_warning");
|
|
var info = "Group Security:Status and Advance:Autoprovisioning can not be both enabled at the same time. Please turn off Group Security:Status first" ;
|
|
modal.find('.modal-body p').text(info);
|
|
modal.find('#button_warning_confirm').click(function () {
|
|
|
|
modal.modal('hide');
|
|
})
|
|
modal.find('#warning_X').click(function () {
|
|
modal.modal('hide');
|
|
})
|
|
modal.modal('show');
|
|
|
|
}
|
|
});
|
|
|
|
$("input[name='purge']" ).change(function(){
|
|
if ($("#purge_on").is(":checked")){
|
|
document.getElementById('purge_on').checked=false;
|
|
document.getElementById('purge_off').checked=true;
|
|
var modal = $("#modal_confirm");
|
|
var info = "Are you sure you want to do this? Users will lose their associated domains unless they already have their autoprovisioning field prepopulated." ;
|
|
modal.find('.modal-body p').text(info);
|
|
modal.find('#button_confirm').click(function () {
|
|
document.getElementById('purge_on').checked=true;
|
|
document.getElementById('purge_off').checked=false;
|
|
modal.modal('hide');
|
|
})
|
|
modal.find('#button_cancel').click(function () {
|
|
modal.modal('hide');
|
|
})
|
|
modal.find('#X').click(function () {
|
|
modal.modal('hide');
|
|
})
|
|
modal.modal('show');
|
|
}
|
|
});
|
|
|
|
$("input[name='ldap_type']" ).change(function(){
|
|
if ($('#ldap').is(":checked") && $('#ldap_enabled').is(":checked")) {
|
|
$('#ldap_admin_group').prop('required', true);
|
|
$('#ldap_operator_group').prop('required', true);
|
|
$('#ldap_user_group').prop('required', true);
|
|
$('#ldap_domain').prop('required', false);
|
|
} else {
|
|
$('#ldap_admin_group').prop('required', false);
|
|
$('#ldap_operator_group').prop('required', false);
|
|
$('#ldap_user_group').prop('required', false);
|
|
$('#ldap_domain').prop('required', true);
|
|
}
|
|
});
|
|
|
|
// init validation requirement at first time page load
|
|
{% if SETTING.get('ldap_enabled') %}
|
|
$('#ldap_uri').prop('required', true);
|
|
$('#ldap_base_dn').prop('required', true);
|
|
if ($('#ldap').is(":checked") ) {
|
|
$('#ldap_admin_username').prop('required', true);
|
|
$('#ldap_admin_password').prop('required', true);
|
|
$('#ldap_domain').prop('required', false);
|
|
} else {
|
|
$('#ldap_admin_username').prop('required', false);
|
|
$('#ldap_admin_password').prop('required', false);
|
|
$('#ldap_domain').prop('required', true);
|
|
}
|
|
$('#ldap_filter_basic').prop('required', true);
|
|
$('#ldap_filter_group').prop('required', true);
|
|
$('#ldap_filter_username').prop('required', true);
|
|
$('#ldap_filter_groupname').prop('required', true);
|
|
|
|
if ($('#ldap_sg_on').is(":checked")) {
|
|
$('#ldap_admin_group').prop('required', true);
|
|
$('#ldap_operator_group').prop('required', true);
|
|
$('#ldap_user_group').prop('required', true);
|
|
}
|
|
|
|
if ($('#autoprovisioning_on').is(":checked")) {
|
|
$('#autoprovisioning_attribute').prop('required', true);
|
|
$('#urn_value').prop('required', true);
|
|
}
|
|
|
|
{% endif %}
|
|
|
|
// END: LDAP tab js
|
|
|
|
// START: Google tab js
|
|
// update validation requirement when checkbox is togged
|
|
$('#google_oauth_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#google_oauth_client_id').prop('required', true);
|
|
$('#google_oauth_client_secret').prop('required', true);
|
|
$('#google_token_url').prop('required', true);
|
|
$('#google_oauth_scope').prop('required', true);
|
|
$('#google_authorize_url').prop('required', true);
|
|
$('#google_base_url').prop('required', true);
|
|
} else {
|
|
$('#google_oauth_client_id').prop('required', false);
|
|
$('#google_oauth_client_secret').prop('required', false);
|
|
$('#google_token_url').prop('required', false);
|
|
$('#google_oauth_scope').prop('required', false);
|
|
$('#google_authorize_url').prop('required', false);
|
|
$('#google_base_url').prop('required', false);
|
|
}
|
|
});
|
|
|
|
// init validation requirement at first time page load
|
|
{% if SETTING.get('google_oauth_enabled') %}
|
|
$('#google_oauth_client_id').prop('required', true);
|
|
$('#google_oauth_client_secret').prop('required', true);
|
|
$('#google_token_url').prop('required', true);
|
|
$('#google_oauth_scope').prop('required', true);
|
|
$('#google_authorize_url').prop('required', true);
|
|
$('#google_base_url').prop('required', true);
|
|
{% endif %}
|
|
// END: Google tab js
|
|
|
|
// START: Github tab js
|
|
// update validation requirement when checkbox is togged
|
|
$('#github_oauth_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#github_oauth_key').prop('required', true);
|
|
$('#github_oauth_secret').prop('required', true);
|
|
$('#github_oauth_scope').prop('required', true);
|
|
$('#github_oauth_api_url').prop('required', true);
|
|
$('#github_oauth_token_url').prop('required', true);
|
|
$('#github_oauth_authorize_url').prop('required', true);
|
|
} else {
|
|
$('#github_oauth_key').prop('required', false);
|
|
$('#github_oauth_secret').prop('required', false);
|
|
$('#github_oauth_scope').prop('required', false);
|
|
$('#github_oauth_api_url').prop('required', false);
|
|
$('#github_oauth_token_url').prop('required', false);
|
|
$('#github_oauth_authorize_url').prop('required', false);
|
|
}
|
|
});
|
|
// init validation requirement at first time page load
|
|
{% if SETTING.get('github_oauth_enabled') %}
|
|
$('#github_oauth_key').prop('required', true);
|
|
$('#github_oauth_secret').prop('required', true);
|
|
$('#github_oauth_scope').prop('required', true);
|
|
$('#github_oauth_api_url').prop('required', true);
|
|
$('#github_oauth_token_url').prop('required', true);
|
|
$('#github_oauth_authorize_url').prop('required', true);
|
|
{% endif %}
|
|
// END: Github tab js
|
|
|
|
// START: Azure tab js
|
|
// update validation requirement when checkbox is togged
|
|
$('#azure_oauth_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#azure_oauth_key').prop('required', true);
|
|
$('#azure_oauth_secret').prop('required', true);
|
|
$('#azure_oauth_scope').prop('required', true);
|
|
$('#azure_oauth_api_url').prop('required', true);
|
|
$('#azure_oauth_token_url').prop('required', true);
|
|
$('#azure_oauth_authorize_url').prop('required', true);
|
|
} else {
|
|
$('#azure_oauth_key').prop('required', false);
|
|
$('#azure_oauth_secret').prop('required', false);
|
|
$('#azure_oauth_scope').prop('required', false);
|
|
$('#azure_oauth_api_url').prop('required', false);
|
|
$('#azure_oauth_token_url').prop('required', false);
|
|
$('#azure_oauth_authorize_url').prop('required', false);
|
|
}
|
|
});
|
|
// init validation requirement at first time page load
|
|
{% if SETTING.get('azure_oauth_enabled') %}
|
|
$('#azure_oauth_key').prop('required', true);
|
|
$('#azure_oauth_secret').prop('required', true);
|
|
$('#azure_oauth_scope').prop('required', true);
|
|
$('#azure_oauth_api_url').prop('required', true);
|
|
$('#azure_oauth_token_url').prop('required', true);
|
|
$('#azure_oauth_authorize_url').prop('required', true);
|
|
{% endif %}
|
|
// END: Azure tab js
|
|
|
|
// START: OIDC tab js
|
|
$('#oidc_oauth_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#oidc_oauth_key').prop('required', true);
|
|
$('#oidc_oauth_secret').prop('required', true);
|
|
$('#oidc_oauth_scope').prop('required', true);
|
|
$('#oidc_oauth_api_url').prop('required', true);
|
|
$('#oidc_oauth_token_url').prop('required', true);
|
|
$('#oidc_oauth_authorize_url').prop('required', true);
|
|
$('#oidc_oauth_username').prop('required', true);
|
|
$('#oidc_oauth_firstname').prop('required', true);
|
|
$('#oidc_oauth_last_name').prop('required', true);
|
|
$('#oidc_oauth_email').prop('required', true);
|
|
} else {
|
|
$('#oidc_oauth_key').prop('required', false);
|
|
$('#oidc_oauth_secret').prop('required', false);
|
|
$('#oidc_oauth_scope').prop('required', false);
|
|
$('#oidc_oauth_api_url').prop('required', false);
|
|
$('#oidc_oauth_token_url').prop('required', false);
|
|
$('#oidc_oauth_authorize_url').prop('required', false);
|
|
$('#oidc_oauth_username').prop('required', false);
|
|
$('#oidc_oauth_firstname').prop('required', false);
|
|
$('#oidc_oauth_last_name').prop('required', false);
|
|
$('#oidc_oauth_email').prop('required', false);
|
|
}
|
|
});
|
|
// init validation requirement at first time page load
|
|
{% if SETTING.get('oidc_oauth_enabled') %}
|
|
$('#oidc_oauth_key').prop('required', true);
|
|
$('#oidc_oauth_secret').prop('required', true);
|
|
$('#oidc_oauth_scope').prop('required', true);
|
|
$('#oidc_oauth_api_url').prop('required', true);
|
|
$('#oidc_oauth_token_url').prop('required', true);
|
|
$('#oidc_oauth_authorize_url').prop('required', true);
|
|
$('#oidc_oauth_username').prop('required', true);
|
|
$('#oidc_oauth_firstname').prop('required', true);
|
|
$('#oidc_oauth_last_name').prop('required', true);
|
|
$('#oidc_oauth_email').prop('required', true);
|
|
{% endif %}
|
|
//END: OIDC Tab JS
|
|
|
|
// START: SAML tab js
|
|
$('#saml_enabled').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#saml_metadata_url').prop('required', true);
|
|
$('#saml_idp_sso_binding').prop('required', true);
|
|
$('#saml_idp_slo_binding').prop('required', true);
|
|
$('#saml_sp_entity_id').prop('required', true);
|
|
$('#saml_nameid_format').prop('required', true);
|
|
$('#saml_sp_acs_binding').prop('required', true);
|
|
$('#saml_sp_sls_binding').prop('required', true);
|
|
$('#saml_sp_requested_attributes').prop('required', true);
|
|
$('#saml_attribute_username').prop('required', true);
|
|
$('#saml_cert_file').prop('required', true);
|
|
$('#saml_cert_key').prop('required', true);
|
|
$('#saml_digest_algorithm').prop('required', true);
|
|
$('#saml_signature_algorithm').prop('required', true);
|
|
if ($('#saml_logout').is(":checked")) {
|
|
$('#saml_logout_url').prop('required', true);
|
|
}
|
|
} else {
|
|
$('#saml_metadata_url').prop('required', false);
|
|
$('#saml_idp_sso_binding').prop('required', false);
|
|
$('#saml_idp_slo_binding').prop('required', false);
|
|
$('#saml_sp_entity_id').prop('required', false);
|
|
$('#saml_nameid_format').prop('required', false);
|
|
$('#saml_sp_acs_binding').prop('required', false);
|
|
$('#saml_sp_sls_binding').prop('required', false);
|
|
$('#saml_sp_requested_attributes').prop('required', false);
|
|
$('#saml_attribute_username').prop('required', false);
|
|
$('#saml_cert_file').prop('required', false);
|
|
$('#saml_cert_key').prop('required', false);
|
|
$('#saml_digest_algorithm').prop('required', false);
|
|
$('#saml_signature_algorithm').prop('required', false);
|
|
$('#saml_logout_url').prop('required', false);
|
|
}
|
|
});
|
|
// init validation requirement at first time page load
|
|
{% if SETTING.get('saml_enabled') %}
|
|
$('#saml_metadata_url').prop('required', true);
|
|
$('#saml_idp_sso_binding').prop('required', true);
|
|
$('#saml_idp_slo_binding').prop('required', true);
|
|
$('#saml_sp_entity_id').prop('required', true);
|
|
$('#saml_nameid_format').prop('required', true);
|
|
$('#saml_sp_acs_binding').prop('required', true);
|
|
$('#saml_sp_sls_binding').prop('required', true);
|
|
$('#saml_sp_requested_attributes').prop('required', true);
|
|
$('#saml_attribute_username').prop('required', true);
|
|
$('#saml_cert_file').prop('required', true);
|
|
$('#saml_cert_key').prop('required', true);
|
|
$('#saml_digest_algorithm').prop('required', true);
|
|
$('#saml_signature_algorithm').prop('required', true);
|
|
if ($('#saml_logout').is(":checked")) {
|
|
$('#saml_logout_url').prop('required', true);
|
|
}
|
|
{% endif %}
|
|
|
|
$(document.body).on("focus", "#saml_sp_requested_attributes", function (e) {
|
|
var req_attr = $(this);
|
|
req_attr.blur();
|
|
var txt_data = req_attr.val();
|
|
var modal = $("#modal_requested_attributes");
|
|
var form = "<textarea spellcheck=\"false\" style=\"min-width: 100%;color: #333;\" placeholder=\"SP Requested Attributes in JSON format\" \
|
|
rows=\"10\" id=\"txt_req_attr\" name=\"txt_req_attr\">" + txt_data + "</textarea>";
|
|
modal.find('.modal-body p').html(form);
|
|
modal.find('#button_save').click(function() {
|
|
data = modal.find('#txt_req_attr').val();
|
|
req_attr.val(data);
|
|
modal.modal('hide');
|
|
});
|
|
modal.modal('show');
|
|
});
|
|
|
|
$('#saml_logout').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
}).on('ifChanged', function(e) {
|
|
var is_enabled = e.currentTarget.checked;
|
|
if (is_enabled){
|
|
$('#saml_logout_url').prop('required', true);
|
|
}
|
|
else{
|
|
$('#saml_logout_url').prop('required', false);
|
|
}
|
|
});
|
|
|
|
$('#saml_sign_authn_request').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_sign_logout_request_response').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_nameid_encrypted').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_want_nameid_encrypted').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_want_assertions_encrypted').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_want_assertions_signed').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_want_message_signed').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
$('#saml_sign_metadata').iCheck({
|
|
checkboxClass : 'icheckbox_square-blue',
|
|
increaseArea : '20%'
|
|
})
|
|
// END: SAML Tab js
|
|
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block modals %}
|
|
<div class="modal fade modal-warning" id="modal_confirm" data-keyboard="false" data-backdrop="static">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close" id="X" >
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title">Confirmation</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-flat btn-default pull-left" id="button_cancel" name="purge" value="OFF" data-dismiss="modal" >Cancel</button>
|
|
<button type="button" class="btn btn-flat btn-success" id="button_confirm">Confirm</button>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
</div>
|
|
<!-- /.modal-dialog -->
|
|
</div>
|
|
|
|
|
|
<div class="modal fade modal-warning" id="modal_warning" data-keyboard="false" data-backdrop="static">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close" id="warning_X" >
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title">Warning</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-flat btn-success" id="button_warning_confirm">Yes I understand</button>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
</div>
|
|
<!-- /.modal-dialog -->
|
|
</div>
|
|
|
|
<div class="modal fade modal-primary" id="modal_requested_attributes">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal"
|
|
aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title">SP Requested Attributes</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-flat btn-primary" id="button_save">Save</button>
|
|
</div>
|
|
</div>
|
|
<!-- /.modal-content -->
|
|
</div>
|
|
<!-- /.modal-dialog -->
|
|
</div>
|
|
|
|
{% endblock %}
|