| <!-- |
| 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"/> 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"/> 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"/> 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: </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"/> {{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"> = <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"/> Users are managed by an external provider.</p> |
| <div id="users-content" ng-show="manageUsersEnabled"> |
| <div id="user-filters"> |
| Filter users by: <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"/> Roles are managed by an external provider.</p> |
| <div id="roles-content" ng-show="manageUserRolesEnabled"> |
| <div id="role-filters"> |
| Filter roles by: <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: <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> |