blob: d8d3093dd7fdf09ae15f14d7436630d0ec8c9bb4 [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div id="securityPanel" class="clearfix">
<div ng-show="isSecurityAdminEnabled && !currentUser">
<p class="error-msg"><img src="img/ico/prohibition.png"/>&nbsp;Current user is not authenticated! Security panel is disabled.</p>
</div>
<div ng-show="isSecurityAdminEnabled && !hasSecurityReadPerm">
<p class="error-msg"><img src="img/ico/prohibition.png"/>&nbsp;You do not have permission to view the security panel.</p>
</div>
<div ng-show="!isSecurityAdminEnabled">
<p class="warning-msg"><img src="img/ico/shield--exclamation.png"/>&nbsp;WARNING: Security is not enabled for this server!</p>
<div ng-show="isCloudMode">
<p class="clearfix">Use the <b>bin/solr auth</b> command-line tool to enable security and then reload this panel. For more information, see: <a target="_blank" href="https://solr.apache.org/guide/authentication-and-authorization-plugins.html#using-security-json-with-solr" class="ref-guide-link">Using security.json with Solr</a></p>
<p class="clearfix"><br/>Example usage of <b>bin/solr auth</b> to enable basic authentication:</p>
<pre>
bin/solr auth enable -type basicAuth -prompt true -z {{zkHost}} -blockUnknown true
</pre>
</div>
<div ng-show="!isCloudMode">
<p class="clearfix">Create a <b>security.json</b> config file in your Solr home directory and then restart Solr (on all nodes). For more information, see: <a target="_blank" href="https://solr.apache.org/guide/authentication-and-authorization-plugins.html#using-security-json-with-solr" class="ref-guide-link">Using security.json with Solr</a></p>
</div>
</div>
<div class="main-col" ng-show="isSecurityAdminEnabled && hasSecurityReadPerm">
<div class="block">
<div id="authn">
<h2><span>Security Settings</span></h2>
<div id="authn-content">
<div id="plugins"><span id="tls">TLS enabled? <img ng-show="tls" src="img/ico/tick.png"/><img ng-show="!tls" src="img/ico/cross.png"/></span>
<span id="authnPlugin">Authentication Plugin: <b>{{authenticationPlugin}}</b><span ng-show="multiAuthWithBasic"><a ng-click="showHelp('multiAuthBasicHelp')"><img class="help-ico" src="img/ico/exclamation-button.png"/></a>
<div id="multiAuthBasicHelp" class="help" ng-show="helpId === 'multiAuthBasicHelp'">
<div class="help-top">
<p>When using the <b>MultiAuthPlugin</b>, changes made to <b>Users</b> and <b>Roles</b>, using the panels below, only affect <b>Basic</b> authentication.<br><br><b>
Users</b> and <b>Roles</b> for the other authentication schemes, such as the <b>Bearer</b> scheme (JWTAuthPlugin), are managed by an external provider.
Thus, not all users with access to the system are displayed below; only users managed by the <b>BasicAuthPlugin</b> are displayed on this screen.
</p>
</div>
</div>
</span>
</span>
<span id="authzPlugin">Authorization Plugin: <b>{{authorizationPlugin}}</b></span></div>
<form>
<span ng-show="manageUsersEnabled" id="realm-field">
<label for="realmName">Realm:&nbsp;</label><input disabled class="input-text" type="text" id="realmName" ng-model="realmName">
</span>
<span id="block-field" ng-show="manageUsersEnabled"><label for="block_unknown">Block anonymous requests?</label><input class="input-check" type="checkbox" id="block_unknown" ng-model="blockUnknown" ng-change="onBlockUnknownChange()" ng-true-value="'true'" ng-false-value="'false'"/><a ng-click="showHelp('blockUnknownHelp')"><img class="help-ico" src="img/ico/question-white.png"/></a>
<div id="blockUnknownHelp" class="help" ng-show="helpId === 'blockUnknownHelp'">
<div class="help-top">
<p>If checked, un-authenticated requests to any Solr endpoint are blocked. If un-checked, then any endpoint that is not protected with a permission will be accessible by anonymous users. Only disable this check if you want to allow un-authenticated access to specific endpoints that are configured with <b>role: null</b>. All other endpoints should be protected with explicit role bindings that require authentication. For more information, see:
<div class="help-anchor"><a target="_blank" href="https://solr.apache.org/guide/basic-authentication-plugin.html#enable-basic-authentication">Basic Authentication</a></div></p>
</div>
</div>
</span>
<span ng-show="manageUsersEnabled" id="forward-field"><label for="forward_creds">Forward credentials?</label><input class="input-check" type="checkbox" id="forward_creds" ng-model="forwardCredentials" ng-change="onForwardCredsChange()" ng-true-value="'true'" ng-false-value="'false'"/><a ng-click="showHelp('forwardCredsHelp')"><img class="help-ico" src="img/ico/question-white.png"/></a>
<div id="forwardCredsHelp" class="help" ng-show="helpId === 'forwardCredsHelp'">
<div class="help-top">
<p>If checked, Solr forwards user credentials when making distributed requests to other nodes in the cluster. If un-checked (the default), Solr will use the internal PKI authentication mechanism for distributed requests. For more information, see:
<div class="help-anchor"><a target="_blank" href="https://solr.apache.org/guide/authentication-and-authorization-plugins.html#pkiauthenticationplugin">PKIAuthenticationPlugin</a></div></p>
</div>
</div>
</span>
</form>
</div>
<div id="error-dialog" class="error-dialog" ng-show="securityAPIError">
<div id="error-dialog-note"><p class="clearfix"><img src="img/ico/prohibition.png"/>&nbsp;{{securityAPIError}}</p></div>
<div id="error-dialog-details"><div ng-show="securityAPIErrorDetails"><textarea rows="10" cols="55">{{securityAPIErrorDetails}}</textarea></div></div>
<div id="error-dialog-buttons" class="clearfix">
<button type="reset" class="error-button" ng-click="closeErrorDialog()"><span>OK</span></button>
</div>
</div>
<div id="user-dialog" class="dialog" ng-show="showUserDialog" escape-pressed="hideAll()">
<div id="user-heading" class="heading">{{userDialogHeader}}<button id="delete-user" ng-show="userDialogMode === 'edit'" class="submit" ng-click="confirmDeleteUser()"><span>Delete</span></button></div>
<form autocomplete="off">
<p class="clearfix"><label for="add_user">Username:</label><input autocomplete="off" ng-disabled="userDialogMode === 'edit'" class="input-text" type="text" id="add_user" ng-model="upsertUser.username" focus-when="showAddField" placeholder="enter a username"></p>
<p class="clearfix"><label for="add_user_roles">Roles:</label><select multiple ng-model="upsertUser.selectedRoles" id="add_user_roles" size="5" ng-options="r for r in roleNames"></select></p>
<p class="clearfix"><label for="add_user">Add New Role:</label><input autocomplete="off" ng-disabled="userDialogMode === 'edit'" class="input-text" type="text" id="add_user_new_role" ng-model="upsertUser.newRole"></p>
<p class="clearfix"><label for="add_user_password">Password:</label><input autocomplete="off" class="input-text" type="password" id="add_user_password" ng-model="upsertUser.password" placeholder="enter a strong password"></p>
<p class="clearfix"><label for="add_user_password2">Confirm password:</label><input autocomplete="off" class="input-text" type="password" id="add_user_password2" ng-model="upsertUser.password2" placeholder="re-enter password"></p>
<div class="formMessageHolder">
<p class="validate-error" ng-show="validationError"><span>{{validationError}}</span></p>
</div>
<p class="clearfix buttons">
<button type="submit" class="submit" ng-click="doUpsertUser()"><span>{{userDialogAction}}</span></button>
<button type="reset" class="reset" ng-click="toggleUserDialog()"><span>Cancel</span></button>
</p>
</form>
</div>
<div id="role-dialog" class="dialog" ng-show="showRoleDialog" escape-pressed="hideAll()">
<div id="role-heading" class="heading">{{roleDialogHeader}}</div>
<form autocomplete="off">
<p class="clearfix"><label for="add_role">Name:</label><input autocomplete="off" ng-disabled="roleDialogMode === 'edit'" class="input-text" type="text" id="add_role" ng-model="upsertRole.name" focus-when="showRoleDialog" placeholder="enter role name"></p>
<p class="clearfix"><label for="add_role_users">Users:</label><select multiple ng-model="upsertRole.selectedUsers" id="add_role_users" size="8" ng-options="u for u in userNames"></select></p>
<!-- <p class="clearfix"><label for="add_role_new_user">Add New User:</label><input class="input-text" type="text" id="add_role_new_user" ng-model="upsertRole.newUser"></p> -->
<p class="clearfix"><label for="add_role_perms">Grant Permissions:</label><select multiple ng-model="upsertRole.grantedPerms" id="add_role_perms" size="8" ng-options="p for p in grantPermissionNames"></select></p>
<div class="formMessageHolder">
<p class="validate-error" ng-show="validationError"><span>{{validationError}}</span></p>
</div>
<p class="clearfix buttons">
<button type="submit" class="submit" ng-click="doUpsertRole()"><span>{{roleDialogAction}}</span></button>
<button type="reset" class="reset" ng-click="toggleRoleDialog()"><span>Cancel</span></button>
</p>
</form>
</div>
<div id="add-permission-dialog" class="dialog" ng-show="showPermDialog" escape-pressed="hideAll()">
<div id="perm-heading" class="heading">{{permDialogHeader}}<button id="delete-perm" ng-show="permDialogMode === 'edit'" class="submit" ng-click="confirmDeletePerm()"><span>Delete</span></button></div>
<form>
<div class="form-field" ng-show="permDialogMode === 'edit'"><label for="add_perm_index">Index:</label><input class="input-text" type="text" id="add_perm_index" ng-model="upsertPerm.index"><a ng-click="showHelp('permIndexHelp')"><img class="help-ico" src="img/ico/question-white.png"/></a>
<div id="permIndexHelp" class="help" ng-show="helpId === 'permIndexHelp'">
<div class="help-index">
<p>For requests where multiple permissions match, Solr applies the first permission that matches based on a complex ordering logic. In general, more specific permissions should be listed earlier in the configuration. The permission index (1-based) governs its position in the configuration. To re-order a permission, change the index to desired position.
<div class="help-anchor"><a target="_blank" href="https://solr.apache.org/guide/rule-based-authorization-plugin.html#permission-ordering-and-resolution">Permission Ordering and Resolution</a></div></p>
</div>
</div>
</div>
<div id="perm-select"><label for="predefined">Predefined:</label><select id="predefined"
chosen disable-search="true" allow-single-deselect="true"
ng-change="onPredefinedChanged()"
ng-model="selectedPredefinedPermission"
ng-disabled="permDialogMode === 'edit'"
ng-options="p for p in filteredPredefinedPermissions">
<option value=""></option>
</select><span id="add_perm_custom">or Custom: <input ng-disabled="permDialogMode === 'edit'" ng-change="onPredefinedChanged()" type="text" id="add_perm_name" ng-model="upsertPerm.name"><a ng-click="showHelp('permDialogHelp')"><img class="help-ico" src="img/ico/question-white.png"/></a>
<div id="permDialogHelp" class="help" ng-show="helpId === 'permDialogHelp'">
<div class="help-perm">
<p>Permissions allow you to grant access to protected resources to one or more roles. Solr provides a list of <b>predefined</b> permissions to cover common use cases, such as collection administration. Otherwise, you can define a <b>custom permission</b> for fine-grained control over the API path(s), collection(s), request method(s) and params.
<div class="help-anchor"><a target="_blank" href="https://solr.apache.org/guide/rule-based-authorization-plugin.html#permissions-2">Rule-based Authorization :: Permissions</a></div></p>
</div>
</div></span>
</div>
<p class="form-field"><label>Roles:</label><select ng-show="manageUserRolesEnabled" multiple ng-model="upsertPerm.selectedRoles" id="add_perm_roles" size="5" ng-options="r for r in roleNamesWithWildcard"></select><input ng-show="!manageUserRolesEnabled" class="input-text" type="text" ng-model="upsertPerm.manualRoles"></p>
<p class="form-field"><label for="add_perm_collection">Collection:</label><input ng-disabled="isPermFieldDisabled" class="input-text" type="text" id="add_perm_collection" ng-model="upsertPerm.collection"></p>
<p class="form-field"><label for="add_perm_path">Path:</label><input ng-disabled="isPermFieldDisabled" type="text" id="add_perm_path" ng-model="upsertPerm.path"></p>
<div class="form-field"><label>Request Method:</label>
<table>
<tr><td><input ng-disabled="isPermFieldDisabled" class="input-check" type="checkbox" id="add_perm_method_get" ng-model="upsertPerm.method.get" ng-true-value="'true'" ng-false-value="'false'"/>GET</td></tr>
<tr><td><input ng-disabled="isPermFieldDisabled" class="input-check" type="checkbox" id="add_perm_method_post" ng-model="upsertPerm.method.post" ng-true-value="'true'" ng-false-value="'false'"/>POST</td></tr>
<tr><td><input ng-disabled="isPermFieldDisabled" class="input-check" type="checkbox" id="add_perm_method_put" ng-model="upsertPerm.method.put" ng-true-value="'true'" ng-false-value="'false'"/>PUT</td></tr>
<tr><td><input ng-disabled="isPermFieldDisabled" class="input-check" type="checkbox" id="add_perm_method_delete" ng-model="upsertPerm.method.delete" ng-true-value="'true'" ng-false-value="'false'"/>DELETE</td></tr>
</table>
</div>
<div class="form-field"><label>Request Params:</label>
<div id="param-rows">
<div class="row clearfix" ng-repeat="p in params">
<input class="param-name" type="text" ng-model="p.name" name="paramName" ng-disabled="isPermFieldDisabled">&nbsp;=&nbsp;<input class="param-value" type="text" ng-model="p.value" name="paramValue" ng-disabled="isPermFieldDisabled">
<div class="param-buttons" ng-show="!isPermFieldDisabled">
<a class="rem" ng-click="removeParam($index)"><span></span></a>
<a class="add" ng-click="addParam($index)"><span></span></a>
</div>
</div>
</div>
</div>
<div class="formMessageHolder">
<p class="validate-error" ng-show="validationError"><span>{{validationError}}</span></p>
</div>
<p class="clearfix buttons">
<button type="submit" class="submit" ng-click="doUpsertPermission()"><span>{{permDialogAction}}</span></button>
<button type="reset" class="reset" ng-click="togglePermDialog()"><span>Cancel</span></button>
</p>
</form>
</div>
</div>
</div>
<div class="block">
<div class="users-left" id="users">
<h2><span>Users</span></h2>
<p ng-show="!manageUsersEnabled" class="external-msg"><img src="img/ico/prohibition.png"/>&nbsp;Users are managed by an external provider.</p>
<div id="users-content" ng-show="manageUsersEnabled">
<div id="user-filters">
Filter users by:&nbsp;<select id="user-filter-type" ng-model="userFilter" ng-change="applyUserFilter()">
<option value=""></option>
<option value="name">name</option>
<option value="role">role</option>
<option value="path">path</option>
<option value="perm">permission</option>
</select>
<select ng-show="userFilter==='role'||userFilter==='perm'" id="user-filter-options" ng-model="userFilterOption" ng-change="onUserFilterOptionChanged()" ng-options="option for option in userFilterOptions"></select>
<input ng-show="userFilter==='name'||userFilter==='path'" type="text" ng-model="userFilterText" id="user-filter-text" ng-change="onUserFilterTextChanged()"/>
<div id="user-actions">
<button id="add-user" class="action" ng-click="showAddUserDialog()" ng-show="hasSecurityEditPerm"><span>Add User</span></button>
</div>
</div>
<div id="users-table">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr ng-class="{odd:$odd}">
<th class="table-hdr td-name">Username</th>
<th class="table-hdr td-roles">Roles</th>
</tr>
<tr class="editable" ng-repeat="u in filteredUsers" ng-class="{odd:$odd}" ng-click="editUser(u)">
<td class="table-data">{{u.username}}</td>
<td class="table-data">{{displayList(u.roles)}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="roles-right" id="roles">
<h2><span>Roles</span></h2>
<p ng-show="!manageUserRolesEnabled" class="external-msg"><img src="img/ico/prohibition.png"/>&nbsp;Roles are managed by an external provider.</p>
<div id="roles-content" ng-show="manageUserRolesEnabled">
<div id="role-filters">
Filter roles by:&nbsp;<select id="role-filter-type" ng-model="roleFilter" ng-change="applyRoleFilter()">
<option value=""></option>
<option value="name">name</option>
<option value="user">user</option>
<option value="path">path</option>
<option value="perm">permission</option>
</select>
<select ng-show="roleFilter==='user'||roleFilter==='perm'" id="role-filter-options" ng-model="roleFilterOption" ng-change="onRoleFilterOptionChanged()" ng-options="option for option in roleFilterOptions"></select>
<input ng-show="roleFilter==='name'||roleFilter==='path'" type="text" ng-model="roleFilterText" id="role-filter-text" ng-change="onRoleFilterTextChanged()"/>
<div id="role-actions">
<button id="add-role" class="action" ng-click="showAddRoleDialog()" ng-show="hasSecurityEditPerm"><span>Add Role</span></button>
</div>
</div>
<div id="roles-table">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr ng-class="{odd:$odd}">
<th class="table-hdr td-role">Role</th>
<th class="table-hdr td-roles">Users</th>
</tr>
<tr class="editable" ng-repeat="r in filteredRoles" ng-class="{odd:$odd}" ng-click="editRole(r)">
<td class="table-data">{{r.name}}</td>
<td class="table-data">{{displayList(r.users)}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="block" id="permissions">
<h2><span>Permissions</span></h2>
<div id="permissions-content">
<div id="perm-filters">
Filter permissions by:&nbsp;<select id="perm-filter-type" ng-model="permFilter" ng-change="applyPermFilter()" ng-options="opt for opt in permFilterTypes"></select>
<select ng-show="permFilter==='role'||permFilter==='user'||permFilter==='collection'" id="perm-filter-options" ng-model="permFilterOption" ng-change="onPermFilterOptionChanged()" ng-options="option for option in permFilterOptions"></select>
<input ng-show="permFilter==='name'||permFilter==='path'" type="text" ng-model="permFilterText" id="perm-filter-text" ng-change="onPermFilterTextChanged()"/>
<div id="perm-actions">
<button id="add-permission" class="action" ng-click="showAddPermDialog()" ng-show="hasSecurityEditPerm && managePermissionsEnabled"><span>Add Permission</span></button>
</div>
</div>
<div id="perms-table">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr ng-class="{odd:$odd}">
<th class="table-hdr td-name">Name</th>
<th class="table-hdr td-roles">Roles</th>
<th class="table-hdr td-coll">Collection</th>
<th class="table-hdr td-path">Path</th>
<th class="table-hdr td-method">Method</th>
<th class="table-hdr td-params">Params</th>
</tr>
<tr class="editable" ng-repeat="p in filteredPerms" ng-class="{odd:$odd}" ng-click="editPerm(p)">
<td class="table-data">{{p.name}}</td>
<td class="table-data">{{displayRoles(p.roles)}}</td>
<td class="table-data">{{p.collectionNames}}</td>
<td class="table-data">{{displayList(p.paths)}}</td>
<td class="table-data">{{displayList(p.method)}}</td>
<td class="table-data">{{displayParams(p.params)}}</td>
</tr>
</tbody>
</table>
</div>
<div ng-show="hasPermWarnings" class="external-msg">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr ng-repeat="w in permWarnings">
<td class="table-warn"><img src="img/ico/exclamation-button.png"/> {{w}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>