master
admingit 2 years ago
parent 147e29b012
commit 64054484f4

@ -0,0 +1,152 @@
# Splunk REST storage/passwords Manager for Splunk
## About
An intuitive, full-featured, Javascript CRUD interface to the [Splunk storage/passwords REST endpoint](http://docs.splunk.com/Documentation/Splunk/7.0.3/RESTREF/RESTaccess#storage.2Fpasswordsstorage/passwords). If you're an app developer looking to securely store passwords for API's, Custom Alert Actions, Modular Inputs or to access any resource that requires a password, this is your tool! Create, update, delete, view passwords, change permissions, sharing and app scope. Ditch your curl commands and upgrade to this simple to use interface.
## Dependencies
To store passwords the user must have the `admin_all_objects` capability enabled within an assigned role. To read passwords a user must have `list_storage_passwords` capabilty enabled within an assigned role.
## Usage
The Credential Management dashboard provides a CRUD interface to create, update and delete credentials to be used within Splunk apps.
#### Create Credential
Simply click the create button to reveal the credential creation form.
![Alt text](appserver/static/img/credential_management-tour:enterprise/credential-create.png?raw=true)
Fill out the form specifying a username, password and optionally a realm. The realm can be used as a descriptor for the credential or left blank; e.g., prod or dev. The form will populate with sane defaults for owner, read users, write users, app scope and sharing. You can update them to whatever you like, including the target app context, before you hit create.
![Alt text](appserver/static/img/credential_management-tour:enterprise/create-form.png?raw=true)
![Alt text](appserver/static/img/credential_management-tour:enterprise/create-success-modal.png?raw=true)
Once created, the dashboard will be refreshed automatically.
![Alt text](appserver/static/img/credential_management-tour:enterprise/table.png?raw=true)
#### Update Credential
Right click on a table entry to reveal a context menu that allows you to update the credential.
![Alt text](appserver/static/img/credential_management-tour:enterprise/context-update.png?raw=true)
Alternatively, you can click the detail view (plus icon) in the table to update the credential.
![Alt text](appserver/static/img/credential_management-tour:enterprise/detail-view.png?raw=true)
The update form will be rendered under the selected row in the table. You can change the password, any of the permissions or the app context when updating. The realm is the only field that cannot be changed. This is a limitation of the storage/passwords REST endpoint, not the app. You don't have to set the password to update the ACL's on the credential or move between apps. Simply choose new permissions or app scope and hit update.
![Alt text](appserver/static/img/credential_management-tour:enterprise/inline-update.png?raw=true)
#### Delete Credential
Right click on a table entry to reveal a context menu that allows you to delete the credential.
![Alt text](appserver/static/img/credential_management-tour:enterprise/context-delete.png?raw=true)
Alternatively, select any individual credential or select all using the checkbox in the header column and press the delte button.
![Alt text](appserver/static/img/credential_management-tour:enterprise/multi-delete.png?raw=true)
![Alt text](appserver/static/img/credential_management-tour:enterprise/multi-delete-confirm.png?raw=true)
#### Reveal Clear Password
Click the eye icon to view the plain text password.
![Alt text](appserver/static/img/credential_management-tour:enterprise/show-password.png?raw=true)
![Alt text](appserver/static/img/credential_management-tour:enterprise/clear-password-modal.png?raw=true)
## Using Stored Passwords
Please see this [awesome blog post](http://www.georgestarcher.com/splunk-stored-encrypted-credentials/) on using your newly stored credentials. When all else fails, dig into [dev.splunk.com](http://dev.splunk.com/search/?q=storage%2Fpasswords&l=en&submit=Search) for more details.
## Credits
Some of the components included in REST storage/passwords Manager App for Splunk are licensed under free or open source licenses. We wish to thank the contributors to those projects.
Twitter Bootstrap dropdown.js v3.3.7
Copyright (c) 2011-2018 Twitter, Inc.
Copyright (c) 2011-2018 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
bootstrap-table.js v1.11.1
(The MIT License)
Copyright (c) 2012-2017 Zhixin Wen <wenzhixin2010@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
bootstrap-table-contextmenu.js v1.1.4
The MIT License (MIT)
Copyright (c) 2015 David Graham
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## Support
### Feature Requests
Please [submit feature requests through Github](https://github.com/sghaskell/rest-storage-passwords-manager/labels/enhancement) using the ``enhancement`` label so they can be tracked and discussed.
### Bugs
Please [submit bugs through Github](https://github.com/sghaskell/rest-storage-passwords-manager/labels/bug) using the ``bug`` label so they can be tracked and discussed.
###### For all other inquiries
Scott Haskell ([shaskell@splunk.com](mailto:shaskell@splunk.com))
###### [Code hosted at Github](https://github.com/sghaskell/rest-storage-passwords-manager)

@ -0,0 +1,133 @@
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _setModalMaxHeight(element) {
this.$element = $(element);
this.$content = this.$element.find('.modal-content');
var borderWidth = this.$content.outerHeight() - this.$content.innerHeight();
var dialogMargin = $(window).width() < 768 ? 20 : 60;
var contentHeight = $(window).height() - (dialogMargin + borderWidth);
var headerHeight = this.$element.find('.modal-header').outerHeight() || 0;
var footerHeight = this.$element.find('.modal-footer').outerHeight() || 0;
var maxHeight = contentHeight - (headerHeight + footerHeight);
this.$content.css({
'overflow': 'hidden'
});
this.$element
.find('.modal-body').css({
'max-height': maxHeight,
'overflow-y': 'auto'
});
}
define(['underscore'], function (_) {
return function () {
/**
* A utility wrapper around Bootstrap's modal.
* @param {string|object} id Either an id or a jQuery element that contains the id in its "data-target" attribute
* @param {object} [options] Bootstrap modal options
* @param {boolean|string} [options.backdrop] Whether or not to show a backdrop, or the string "static" to show a backdrop that doesn't close the modal when clicked
* @param {boolean} [options.keyboard] Whether or not the escape key clsoes the modal
* @param {boolean} [options.show=false] Whether or not to show the modal when it's created
* @param {string} [options.type='normal'] Can be 'normal', 'wide', or 'noPadding'
* @param {string} [options.title] The modal's title
* @param {boolean} [options.destroyOnHide=true] Destroy the modal when it's hidden
* @returns {element}
*/
function Modal(id, options) {
var _this = this;
_classCallCheck(this, Modal);
var modalOptions = _.extend({ show: false}, options);
// if "id" is the element that triggers the modal display, extract the actual id from it; otherwise use it as-is
var modalId = id != null && (typeof id === 'undefined' ? 'undefined' : _typeof(id)) === 'object' && id.jquery != null ? id.attr('data-target').slice(1) : id;
var header = $('<div>').addClass('modal-header');
var headerCloseButton = $('<button>').addClass('close').attr({
'type': 'button',
'data-dismiss': 'modal',
'aria-label': 'Close'
}).append($('<span>').attr('aria-hidden', true).text('&times;'));
this.title = $('<h3>').addClass('modal-title');
this.body = $('<div>').addClass('modal-body');
this.footer = $('<div>').addClass('modal-footer');
// Multiselect can grow large and step over footer causing issues clicking button in footer
this.footer.css('position', 'relative');
this.footer.css('z-index', 1);
this.$el = $('<div>').addClass('modal hide fade mlts-modal').attr('id', modalId).append($('<div>').addClass('modal-dialog').append($('<div>').addClass('modal-content').append(header.append(headerCloseButton, this.title), this.body, this.footer)));
if (modalOptions.title != null) this.setTitle(modalOptions.title);
if (modalOptions.type === 'wide') this.$el.addClass('modal-wide');else if (modalOptions.type === 'noPadding') this.$el.addClass('mlts-modal-no-padding');
// remove the modal from the dom after it's hidden
if (modalOptions.destroyOnHide !== false) {
this.$el.on('hidden.bs.modal', function () {
return _this.$el.remove();
});
}
this.$el.on('show.bs.modal', function() {
$(this).show();
_setModalMaxHeight(this);
});
$(window).resize(function() {
if ($('.modal.in').length != 0) {
_setModalMaxHeight($('.modal.in'));
}
});
this.$el.modal(modalOptions);
}
_createClass(Modal, [{
key: 'setTitle',
value: function setTitle(titleText) {
this.title.text(titleText);
}
}, {
key: 'setAlert',
value: function setAlert(alertMessage, alertType) {
if (this.alert == null) {
this.alert = $('<div>').addClass('mlts-modal-alert');
this.body.prepend(this.alert);
}
//Messages.setAlert(this.alert, alertMessage, alertType, undefined, true);
}
}, {
key: 'removeAlert',
value: function removeAlert() {
//Messages.removeAlert(this.alert, true);
}
}, {
key: 'show',
value: function show() {
this.$el.modal('show');
}
}, {
key: 'hide',
value: function hide() {
this.$el.modal('hide');
}
}]);
return Modal;
}();
});

@ -0,0 +1,61 @@
.btn-danger {
color: #fff;
background-color: #d9534f;
border-color: #d43f3a;
box-shadow: inset 0 1px 0 #d43f3a;
text-shadow: none;
}
.btn-danger:hover {
color: #fff;
background-color: #c9302c;
border-color: #ac2925;
background-image: linear-gradient(180deg,#ee5f5b,#bd362f);
}
.btn.disabled, .btn.disabled:focus, .btn.disabled:hover, .btn[disabled], .btn[disabled]:focus, .btn[disabled]:hover {
cursor: not-allowed;
color: #fff;
text-shadow: none;
opacity: .65;
box-shadow: none;
background-image: linear-gradient(180deg,#ee5f5b,#bd362f);
}
.btn-danger.active,
.btn-danger.disabled,
.btn-danger:active,
.btn-danger:focus,
.btn-danger:hover,
.btn-danger[disabled] {
color: #fff;
background-color: #bd362f;
background-image: linear-gradient(180deg,#c9302c,#ac2925);
}
.alert {
margin-bottom: 0px;
border-radius: 4px;
position: relative;
padding: 8px 35px 8px 27px;
word-wrap: break-word;
color: #333;
}
[class*=" icon-check-circle"]:before, [class^=icon-check-circle]:before {
font-family: Splunk Icons;
font-style: normal;
font-weight: 400;
text-decoration: inherit;
line-height: inherit;
font-size: 20px;
color: #5cc05c;
}
[class*=" icon-visible"]:before, [class^=icon-visible]:before {
font-family: Splunk Icons;
font-style: normal;
font-weight: 400;
text-decoration: inherit;
line-height: inherit;
font-size: 22px;
}

@ -0,0 +1,324 @@
.dropup,
.dropdown {
position: relative;
}
.dropup .caret,
.dropdown .caret {
border-bottom: none;
}
/*
.dropdown-toggle::after {
display: inline-block;
width: 0;
height: 0;
margin-left: 0.3em;
vertical-align: middle;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-left: 0.3em solid transparent;
}
*/
.dropdown-toggle:focus {
outline: 0;
}
.dropup .dropdown-toggle::after {
border-top: 0;
border-bottom: 0.3em solid;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
/* padding: 0.5rem 0; */
margin: 0.125rem 0 0;
/* font-size: 1rem; */
color: #292b2c;
text-align: left;
list-style: none;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
}
.dropdown-divider {
height: 1px;
margin: 0.5rem 0;
overflow: hidden;
background-color: #eceeef;
}
.dropdown-item {
display: block;
width: 100%;
padding: 3px 1.5rem;
clear: both;
font-weight: normal;
color: #292b2c;
text-align: inherit;
white-space: nowrap;
background: none;
border: 0;
}
.dropdown-item:focus, .dropdown-item:hover {
color: #1d1e1f;
text-decoration: none;
background-color: #f7f7f9;
}
.dropdown-item.active, .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #0275d8;
}
.dropdown-item.disabled, .dropdown-item:disabled {
color: #636c72;
cursor: not-allowed;
background-color: transparent;
}
.show > .dropdown-menu {
display: block;
}
.show > a {
outline: 0;
}
.dropdown-menu-right {
right: 0;
left: auto;
}
.dropdown-menu-left {
right: auto;
left: 0;
}
.dropdown-header {
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
color: #636c72;
white-space: nowrap;
}
.dropdown-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 990;
}
.dropup .dropdown-menu {
top: auto;
bottom: 100%;
margin-bottom: 0.125rem;
}
.btn-group,
.btn-group-vertical {
position: relative;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
vertical-align: middle;
}
.btn-group > .btn,
.btn-group-vertical > .btn {
position: relative;
-webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
}
.btn-group > .btn:hover,
.btn-group-vertical > .btn:hover {
z-index: 2;
}
.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
.btn-group-vertical > .btn:focus,
.btn-group-vertical > .btn:active,
.btn-group-vertical > .btn.active {
z-index: 2;
}
.btn-group .btn + .btn,
.btn-group .btn + .btn-group,
.btn-group .btn-group + .btn,
.btn-group .btn-group + .btn-group,
.btn-group-vertical .btn + .btn,
.btn-group-vertical .btn + .btn-group,
.btn-group-vertical .btn-group + .btn,
.btn-group-vertical .btn-group + .btn-group {
margin-left: -1px;
}
.btn-toolbar {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.btn-toolbar .input-group {
width: auto;
}
.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
border-radius: 0;
}
.btn-group > .btn:first-child {
margin-left: 0;
}
.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
.btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
.btn-group > .btn-group {
float: left;
}
.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
.btn-group .dropdown-toggle:active,
.btn-group.open .dropdown-toggle {
outline: 0;
}
.btn + .dropdown-toggle-split {
padding-right: 0.75rem;
padding-left: 0.75rem;
}
.btn + .dropdown-toggle-split::after {
margin-left: 0;
}
.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
padding-right: 0.375rem;
padding-left: 0.375rem;
}
.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
padding-right: 1.125rem;
padding-left: 1.125rem;
}
.btn-group-vertical {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.btn-group-vertical .btn,
.btn-group-vertical .btn-group {
width: 100%;
}
.btn-group-vertical > .btn + .btn,
.btn-group-vertical > .btn + .btn-group,
.btn-group-vertical > .btn-group + .btn,
.btn-group-vertical > .btn-group + .btn-group {
margin-top: -1px;
margin-left: 0;
}
.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
border-radius: 0;
}
.btn-group-vertical > .btn:first-child:not(:last-child) {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.btn-group-vertical > .btn:last-child:not(:first-child) {
border-top-right-radius: 0;
border-top-left-radius: 0;
}
.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
border-top-right-radius: 0;
border-top-left-radius: 0;
}
[data-toggle="buttons"] > .btn input[type="radio"],
[data-toggle="buttons"] > .btn input[type="checkbox"],
[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
}

@ -0,0 +1,165 @@
/* ========================================================================
* Bootstrap: dropdown.js v3.3.7
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
* Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle="dropdown"]'
var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle)
}
Dropdown.VERSION = '3.3.7'
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
function clearMenus(e) {
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
var $this = $(this)
var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return
if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
})
}
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
$(document.createElement('div'))
.addClass('dropdown-backdrop')
.insertAfter($(this))
.on('click', clearMenus)
}
var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this
.trigger('focus')
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger($.Event('shown.bs.dropdown', relatedTarget))
}
return false
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if (!isActive && e.which != 27 || isActive && e.which == 27) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
var desc = ' li:not(.disabled):visible a'
var $items = $parent.find('.dropdown-menu' + desc)
if (!$items.length) return
var index = $items.index(e.target)
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.dropdown')
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
}(jQuery);

@ -0,0 +1,170 @@
/**
* @author David Graham <prograhammer@gmail.com>
* @version v1.1.4
* @link https://github.com/prograhammer/bootstrap-table-contextmenu
*/
!function($) {
'use strict';
$.extend($.fn.bootstrapTable.defaults, {
// Option defaults
contextMenu: undefined,
contextMenuTrigger: 'right',
contextMenuAutoClickRow: true,
contextMenuButton: undefined,
beforeContextMenuRow: function (e, row, buttonElement) {
// return false here to prevent menu showing
},
// Event default handlers
onContextMenuItem: function (row, $element) {
return false;
},
onContextMenuRow: function (row, $element) {
return false;
}
});
// Methods
$.fn.bootstrapTable.methods.push('showContextMenu');
// Events
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'contextmenu-item.bs.table': 'onContextMenuItem',
'contextmenu-row.bs.table': 'onContextMenuRow'
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initBody = BootstrapTable.prototype.initBody;
BootstrapTable.prototype.initBody = function () {
// Init Body
_initBody.apply(this, Array.prototype.slice.apply(arguments));
// Init Context menu
if (this.options.contextMenu || this.options.contextMenuButton || this.options.beforeContextMenuRow) {
this.initContextMenu();
}
};
// Init context menu
BootstrapTable.prototype.initContextMenu = function () {
var that = this;
// Context menu on Right-click
if (that.options.contextMenuTrigger == 'right' || that.options.contextMenuTrigger == 'both') {
that.$body.find('> tr[data-index]').off('contextmenu.contextmenu').on('contextmenu.contextmenu', function (e) {
var rowData = that.data[$(this).data('index')],
beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, null]);
if(beforeShow !== false){
that.showContextMenu({event: e});
}
return false;
});
}
// Context menu on Left-click
if (that.options.contextMenuTrigger == 'left' || that.options.contextMenuTrigger == 'both') {
that.$body.find('> tr[data-index]').off('click.contextmenu').on('click.contextmenu', function (e) {
var rowData = that.data[$(this).data('index')],
beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, null]);
if(beforeShow !== false){
that.showContextMenu({event: e});
}
return false;
});
}
// Context menu on Button-click
if (typeof that.options.contextMenuButton === 'string') {
that.$body.find('> tr[data-index]').find(that.options.contextMenuButton).off('click.contextmenu').on('click.contextmenu', function (e) {
var rowData = that.data[$(this).closest('tr[data-index]').data('index')],
beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, this]);
if(beforeShow !== false){
that.showContextMenu({event: e, buttonElement: this});
}
return false;
});
}
};
// Show context menu
BootstrapTable.prototype.showContextMenu = function (params) {
if(!params || !params.event){ return false; }
if(params && !params.contextMenu && typeof this.options.contextMenu !== 'string'){ return false; }
var that = this,
$menu, screenPosX, screenPosY,
$tr = $(params.event.target).closest('tr[data-index]'),
item = that.data[$tr.data('index')];
if(params && !params.contextMenu && typeof this.options.contextMenu === 'string'){
screenPosX = params.event.clientX;
screenPosY = params.event.clientY;
$menu = $(this.options.contextMenu);
}
if(params && params.contextMenu){
screenPosX = params.event.clientX;
screenPosY = params.event.clientY;
$menu = $(params.contextMenu);
}
if (params && params.buttonElement) {
screenPosX = params.buttonElement.getBoundingClientRect().left;
screenPosY = params.buttonElement.getBoundingClientRect().bottom;
}
function getMenuPosition($menu, screenPos, direction, scrollDir) {
var win = $(window)[direction](),
scroll = $(window)[scrollDir](),
menu = $menu[direction](),
position = screenPos + scroll;
if (screenPos + menu > win && menu < screenPos)
position -= menu;
return position;
}
// Bind click on menu item
$menu.find('li').off('click.contextmenu').on('click.contextmenu', function (e) {
var rowData = that.data[$menu.data('index')];
that.trigger('contextmenu-item', rowData, $(this));
});
// Click anywhere to hide the menu
$(document).triggerHandler('click.contextmenu');
$(document).off('click.contextmenu').on('click.contextmenu', function (e) {
// Fixes problem on Mac OSX
if(that.pageX != e.pageX || that.pageY != e.pageY){
$menu.hide();
$(document).off('click.contextmenu');
}
});
that.pageX = params.event.pageX;
that.pageY = params.event.pageY;
// Show the menu
$menu.data('index', $tr.data('index'))
.appendTo($('body'))
.css({
position: "absolute",
left: getMenuPosition($menu, screenPosX, 'width', 'scrollLeft'),
top: getMenuPosition($menu, screenPosY, 'height', 'scrollTop'),
zIndex: 1100
})
.show();
// Trigger events
that.trigger('contextmenu-row', item, $tr);
if(that.options.contextMenuAutoClickRow && that.options.contextMenuTrigger == 'right') {
that.trigger('click-row', item, $tr);
}
};
}(jQuery);

@ -0,0 +1,313 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.11.1
* https://github.com/wenzhixin/bootstrap-table/
*/
.bootstrap-table .table {
margin-bottom: 0 !important;
border-bottom: 1px solid #dddddd;
border-collapse: collapse !important;
border-radius: 1px;
}
.bootstrap-table .table:not(.table-condensed),
.bootstrap-table .table:not(.table-condensed) > tbody > tr > th,
.bootstrap-table .table:not(.table-condensed) > tfoot > tr > th,
.bootstrap-table .table:not(.table-condensed) > thead > tr > td,
.bootstrap-table .table:not(.table-condensed) > tbody > tr > td,
.bootstrap-table .table:not(.table-condensed) > tfoot > tr > td {
padding: 8px;
}
.bootstrap-table .table.table-no-bordered > thead > tr > th,
.bootstrap-table .table.table-no-bordered > tbody > tr > td {
border-right: 2px solid transparent;
}
.bootstrap-table .table.table-no-bordered > tbody > tr > td:last-child {
border-right: none;
}
.fixed-table-container {
position: relative;
clear: both;
border: 1px solid #dddddd;
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
}
.fixed-table-container.table-no-bordered {
border: 1px solid transparent;
}
.fixed-table-footer,
.fixed-table-header {
overflow: hidden;
}
.fixed-table-footer {
border-top: 1px solid #dddddd;
}
.fixed-table-body {
overflow-x: auto;
overflow-y: auto;
height: 100%;
}
.fixed-table-container table {
width: 100%;
}
.fixed-table-container thead th {
height: 0;
padding: 0;
margin: 0;
border-left: 1px solid #dddddd;
}
.fixed-table-container thead th:focus {
outline: 0 solid transparent;
}
.fixed-table-container thead th:first-child {
border-left: none;
border-top-left-radius: 4px;
-webkit-border-top-left-radius: 4px;
-moz-border-radius-topleft: 4px;
}
.fixed-table-container thead th .th-inner,
.fixed-table-container tbody td .th-inner {
padding: 8px;
line-height: 24px;
vertical-align: top;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.fixed-table-container thead th .sortable {
cursor: pointer;
background-position: right;
background-repeat: no-repeat;
padding-right: 30px;
}
.fixed-table-container thead th .both {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC');
}
.fixed-table-container thead th .asc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==');
}
.fixed-table-container thead th .desc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ');
}
.fixed-table-container th.detail {
width: 30px;
}
.fixed-table-container tbody td {
border-left: 1px solid #dddddd;
}
.fixed-table-container tbody tr:first-child td {
border-top: none;
}
.fixed-table-container tbody td:first-child {
border-left: none;
}
/* the same color with .active */
.fixed-table-container tbody .selected td {
background-color: #f5f5f5;
}
.fixed-table-container .bs-checkbox {
text-align: center;
}
.fixed-table-container .bs-checkbox .th-inner {
padding: 8px 0;
}
.fixed-table-container input[type="radio"],
.fixed-table-container input[type="checkbox"] {
margin: 0 auto !important;
}
.fixed-table-container .no-records-found {
text-align: center;
}
.fixed-table-pagination div.pagination,
.fixed-table-pagination .pagination-detail {
margin-top: 10px;
margin-bottom: 10px;
}
.fixed-table-pagination div.pagination .pagination {
margin: 0;
}
.fixed-table-pagination .pagination a {
padding: 6px 12px;
line-height: 1.428571429;
}
.fixed-table-pagination .pagination-info {
line-height: 34px;
margin-right: 5px;
}
.fixed-table-pagination .btn-group {
position: relative;
display: inline-block;
vertical-align: middle;
}
.fixed-table-pagination .dropup .dropdown-menu {
margin-bottom: 0;
}
.fixed-table-pagination .page-list {
display: inline-block;
}
.fixed-table-toolbar .columns-left {
margin-right: 5px;
}
.fixed-table-toolbar .columns-right {
margin-left: 5px;
}
.fixed-table-toolbar .columns label {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.428571429;
}
.fixed-table-toolbar .bs-bars,
.fixed-table-toolbar .search,
.fixed-table-toolbar .columns {
position: relative;
margin-top: 10px;
margin-bottom: 10px;
line-height: 34px;
}
.fixed-table-pagination li.disabled a {
pointer-events: none;
cursor: default;
}
.fixed-table-loading {
display: none;
position: absolute;
top: 42px;
right: 0;
bottom: 0;
left: 0;
z-index: 99;
background-color: #fff;
text-align: center;
}
.fixed-table-body .card-view .title {
font-weight: bold;
display: inline-block;
min-width: 30%;
text-align: left !important;
}
/* support bootstrap 2 */
.fixed-table-body thead th .th-inner {
box-sizing: border-box;
}
.table th, .table td {
vertical-align: middle;
box-sizing: border-box;
}
.fixed-table-toolbar .dropdown-menu {
text-align: left;
max-height: 300px;
overflow: auto;
}
.fixed-table-toolbar .btn-group > .btn-group {
display: inline-block;
margin-left: -1px !important;
}
.fixed-table-toolbar .btn-group > .btn-group > .btn {
border-radius: 0;
}
.fixed-table-toolbar .btn-group > .btn-group:first-child > .btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.fixed-table-toolbar .btn-group > .btn-group:last-child > .btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.bootstrap-table .table > thead > tr > th {
vertical-align: bottom;
border-bottom: 1px solid #ddd;
}
/* support bootstrap 3 */
.bootstrap-table .table thead > tr > th {
padding: 0;
margin: 0;
}
.bootstrap-table .fixed-table-footer tbody > tr > td {
padding: 0 !important;
}
.bootstrap-table .fixed-table-footer .table {
border-bottom: none;
border-radius: 0;
padding: 0 !important;
}
.bootstrap-table .pull-right .dropdown-menu {
right: 0;
left: auto;
}
/* calculate scrollbar width */
p.fixed-table-scroll-inner {
width: 100%;
height: 200px;
}
div.fixed-table-scroll-outer {
top: 0;
left: 0;
visibility: hidden;
width: 200px;
height: 150px;
overflow: hidden;
}
/* for get correct heights */
.fixed-table-toolbar:after, .fixed-table-pagination:after {
content: "";
display: block;
clear: both;
}

@ -0,0 +1 @@
This is where you put any scripts you want to add to this app.

@ -0,0 +1,20 @@
#
# Splunk app configuration file
#
[install]
is_configured = 0
state_change_requires_restart = false
[ui]
is_visible = 1
label = REST storage/passwords Manager for Splunk
[launcher]
author = Scott Haskell
description = An intuitive, full-featured, Javascript CRUD interface to the storage/passwords REST endpoint.
version = 1.0.8
[package]
id = rest-storage-passwords-manager
check_for_updates = 1

@ -0,0 +1,4 @@
<nav search_view="credential_management" color="#65A637">
<view name="credential_management" />
<view name="help" />
</nav>

@ -0,0 +1,8 @@
<panel>
<html>
<div id="create-user"/>
<div id="update-user"/>
<div id="context-menu"/>
<div id="password-table"/>
</html>
</panel>

@ -0,0 +1 @@
Add all the views that your app needs in this directory

@ -0,0 +1,13 @@
<dashboard script="bootstrap-dropdown.js,bootstrap-table.js,bootstrap-table-contextmenu.js,password-crud.js" stylesheet="bootstrap-table.css, bootstrap-dropdown.css, bootstrap-btn-danger.css" refresh="300">
<label>Credential Management</label>
<row>
<panel>
<html>
<div id="create-user"></div>
<div id="update-user"></div>
<div id="context-menu"></div>
<div id="password-table"></div>
</html>
</panel>
</row>
</dashboard>

@ -0,0 +1,47 @@
<dashboard>
<label>Help</label>
<row>
<html><h1 id="splunkreststoragepasswordsmanager">Splunk REST storage/passwords Manager for Splunk</h1>
<h2 id="about">About</h2>
<p>The password manager app provides a Javascript CRUD interface to the <a href="http://docs.splunk.com/Documentation/Splunk/7.0.3/RESTREF/RESTaccess#storage.2Fpasswords">Splunk storage/passwords REST endpoint</a>. </p>
<h2 id="dependencies">Dependencies</h2>
<p>To store passwords the user must have the <code>admin_all_objects</code> capability enabled within an assigned role. To read passwords a user must have <code>list_storage_passwords</code> capabilty enabled within an assigned role.</p>
<h2 id="usage">Usage</h2>
<p>The Credential Management dashboard provides a CRUD interface to create, update and delete credentials to be used within Splunk apps. </p>
<h4 id="createcredential">Create Credential</h4>
<p>Simply click the create button to reveal the credential creation form.</p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/credential-create.png?raw=true" alt="Alt text" /></p>
<p>Fill out the form specifying a username, password and optionally a realm. The realm can be used as a descriptor for the credential or left blank; e.g., prod or dev. The form will populate with sane defaults for owner, read users, write users, app scope and sharing. You can update them to whatever you like, including the target app context, before you hit create.</p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/create-form.png?raw=true" alt="Alt text" /></p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/create-success-modal.png?raw=true" alt="Alt text" /></p>
<p>Once created, the dashboard will be refreshed automatically. </p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/table.png?raw=true" alt="Alt text" /></p>
<h4 id="updatecredential">Update Credential</h4>
<p>Right click on a table entry to reveal a context menu that allows you to update the credential. </p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/context-update.png?raw=true" alt="Alt text" /></p>
<p>Alternately, you can click the detail view (plus icon) in the table to update the credential.</p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/detail-view.png?raw=true" alt="Alt text" /></p>
<p>The update form will be rendered under the selected row in the table. You can change the password, any of the permissions or the app context when updating. The realm is the only field that cannot be changed. This is a limitation of the storage/passwords REST endpoint, not the app. You don't have to set the password to update the ACL's on the credential or move between apps. Simply choose new permissions or app scope and hit update.</p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/inline-update.png?raw=true" alt="Alt text" /></p>
<h4 id="deletecredential">Delete Credential</h4>
<p>Right click on a table entry to reveal a context menu that allows you to delete the credential. </p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/context-delete.png?raw=true" alt="Alt text" /></p>
<p>Alternately, select any individual credential or select all using the checkbox in the header column and press the delte button.</p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/multi-delete.png?raw=true" alt="Alt text" /></p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/multi-delete-confirm.png?raw=true" alt="Alt text" /></p>
<h4 id="revealclearpassword">Reveal Clear Password</h4>
<p>Click the eye icon to view the plain text password.</p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/show-password.png?raw=true" alt="Alt text" /></p>
<p><img src="/static/app/rest-storage-passwords-manager/img/credential_management-tour:enterprise/clear-password-modal.png?raw=true" alt="Alt text" /></p>
<h2 id="usingstoredpasswords">Using Stored Passwords</h2>
<p>Please see this <a href="http://www.georgestarcher.com/splunk-stored-encrypted-credentials/">awesome blog post</a> on using your newly stored credentials. When all else fails, dig into <a href="http://dev.splunk.com/search/?q=storage%2Fpasswords">dev.splunk.com</a> for more details.</p>
<h2 id="support">Support</h2>
<h3 id="featurerequests">Feature Requests</h3>
<p>Please <a href="https://github.com/sghaskell/rest-storage-passwords-manager/labels/enhancement">submit feature requests through Github</a> using the <code>enhancement</code> label so they can be tracked and discussed.</p>
<h3 id="bugs">Bugs</h3>
<p>Please <a href="https://github.com/sghaskell/rest-storage-passwords-manager/labels/bug">submit bugs through Github</a> using the <code>bug</code> label so they can be tracked and discussed.</p>
<h6 id="forallotherinquiries">For all other inquiries</h6>
<p>Scott Haskell (<a href="mailto:shaskell@splunk.com">shaskell@splunk.com</a>)</p>
<h6 id="codehostedatgithubhttpsgithubcomsghaskellreststoragepasswordsmanager"><a href="https://github.com/sghaskell/rest-storage-passwords-manager">Code hosted at Github</a></h6></html>
</row>
</dashboard>

@ -0,0 +1,26 @@
[credential_management-tour:enterprise]
context = rest-storage-passwords-manager
imgPath = /credential_management-tour:enterprise
label = rest-storage-passwords-manager-tour
type = image
doneURL = /app/rest-storage-passwords-manager/credential_management
imageCaption1 = Create
imageName1 = credential-create.png
skipText = Skip tour
imageCaption2 = Specify username, password, realm (optional - e.g., prod or dev), read/write permissions, app scope and sharing.
imageName2 = create-form.png
imageCaption3 = Right click on row to update via context menu
imageName3 = context-update.png
imageCaption4 = Use the detail view to update a row
imageName4 = detail-view.png
imageCaption5 = Update password, permissions, app scope or sharing for the credential
imageName5 = inline-update.png
imageCaption6 = Right click on a row to delete via the context menu
imageName6 = context-delete.png
imageCaption7 = Delete multiple credentials by selecting individual rows or use the select all checkbox in the table header and click delete
imageName7 = multi-delete.png
imageCaption8 = Reveal the clear text password for a credential
imageName8 = show-password.png
imageCaption9 = The Dude abides!
imageName9 = clear-password-modal.png
viewed = 0

@ -0,0 +1,3 @@
[expose:configs_conf-PASSWORDS_MOVE]
methods = POST
pattern = configs/conf-passwords/*/move

@ -0,0 +1,12 @@
[]
export = system
[views/credential_management]
access = read : [ * ]
export = none
owner = nobody
[views/help]
access = read : [ * ]
export = none
owner = nobody

@ -0,0 +1,194 @@
{
"version": "1.0",
"date": "2022-11-14T09:53:21.380255565Z",
"hashAlgorithm": "SHA-256",
"app": {
"id": 4013,
"version": "1.0.8",
"files": [
{
"path": "README.md",
"hash": "17917df1b2742bf6ced6529ad9b5a388f830ef8e2b0bc8cde7a73f6359e6c2c5"
},
{
"path": "appserver/static/Modal.js",
"hash": "86c6704ab58ca8527cafe352f15381cf28dc0493accb8e335a461c93f93d4f59"
},
{
"path": "appserver/static/bootstrap-btn-danger.css",
"hash": "92f3372b358f048e72cf443ec43b65ba9b0281e81d1da8a13328ed99166e23c9"
},
{
"path": "appserver/static/bootstrap-dropdown.css",
"hash": "17c1446fbbcf629f3c9c6f07babcd6e672ab6c68f48333ee1c628152785754c7"
},
{
"path": "appserver/static/bootstrap-dropdown.js",
"hash": "1e27ab65eddd056cf3bf185c8a4784c53e5657faeadbb6742830d0f1367f638f"
},
{
"path": "appserver/static/bootstrap-table-contextmenu.js",
"hash": "4498c41efcf6a551260efc7bbdc37cb53b83ecb6c7d8d62e99f2ac563ee5183d"
},
{
"path": "appserver/static/bootstrap-table.css",
"hash": "72805bd7db12be1db2918f9f41096b92c48f618865a7d43ff3bedfa9223ebe42"
},
{
"path": "appserver/static/bootstrap-table.js",
"hash": "e477192a88ad98341e4db3122706c526f50e5353b3d81a619813e2eafcdce717"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/clear-password-modal.png",
"hash": "00a55d412d8ccd7e57404fe348020e465b3b570b7823a62a6862b7afb9c47123"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/context-delete.png",
"hash": "8acd50c1563a144572925e929790602c86cf4b40a3a95f04344ae9269c84752d"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/context-menu.png",
"hash": "f00f0a3e8d8898bf04f0574fcb48d5cffa409bdb14bd0d8741f7994a9396eda1"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/context-update.png",
"hash": "43bf7a6c56c9d57305fc0d61dbade90ac212dca546e23e54422ca69711e5cc75"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/create-form.png",
"hash": "2c6656d39f432bf3ae612e9e83b17b2b96aaeb08aa9c8caf687ef80773a68309"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/create-success-modal.png",
"hash": "ecaf138a7d423cba326d9b96665e0bfbbc85c979a687c6b44ba9741f589546d0"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/credential-create.png",
"hash": "c27abf488122cee4851f055db2324c39a022c08ccb5d37acb8a7461d12ded463"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/detail-view.png",
"hash": "37091e1a66a36d50ce8f46d710f110843c161c834e177a0acd1f80d1d06e6452"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/filter.png",
"hash": "ad0363ff48bd0f3553f1d968e96e29eb1f732b006cda2686272449cda4bf1e05"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/inline-update.png",
"hash": "9f5911e98e630a49663bffd1d03e5e1bf01ca5dbba6537144d2e6482da0fbdb0"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/multi-delete-confirm.png",
"hash": "c9adaf61556c5267c6d79a497d5892c0f08fb3f64ffe5e15954b5cf6a65ece1b"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/multi-delete.png",
"hash": "a2b6a9ccca6b61fbc640d521a7ad229a9de0e28ab7663323bc854cc6f418c3d7"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/show-password.png",
"hash": "0ed1bb7e0b6b1d5d55a9f03eda9db4b22783719f2ec971a26da61aeee4ab6365"
},
{
"path": "appserver/static/img/credential_management-tour:enterprise/table.png",
"hash": "77b7c9f782d629121f8b5f359b9816eb852f3c99dd868106827ed90ad072c763"
},
{
"path": "appserver/static/password-crud.js",
"hash": "097bd3e3c74f0ff8e2b834c00b71141ba56c8dc945e91cd6a41ed585ee06247e"
},
{
"path": "bin/README",
"hash": "597cdad620bec4e52e0e8adc3cad99de9b3ce45da0dd18e4159e1009c976e957"
},
{
"path": "default/app.conf",
"hash": "2c081ec42551be5ff60e81cece40a5a2529c69b1538cbc88b63899a59c759ced"
},
{
"path": "default/data/ui/nav/default.xml",
"hash": "61ff3213833d58ffe188165b2c471bcf190a817544a6b0c5e15395b45e8de40c"
},
{
"path": "default/data/ui/panels/credential-management.xml",
"hash": "3f94d92418394f18c6679aa6ac261faf312e7bfadfdcd04f8eb0f1b90211bb08"
},
{
"path": "default/data/ui/views/README",
"hash": "4ccd9dc2dca5bd634f7c07ad1749e4e63a7969c84e2eff83517256f7c884cd29"
},
{
"path": "default/data/ui/views/credential_management.xml",
"hash": "cb253d7f6279d28091bb008737d400f62f3072f5e8395bc84d619bf990da5c1a"
},
{
"path": "default/data/ui/views/help.xml",
"hash": "d6ea7a342026d1c2f159d2b31b3bef8da2da3ec683f9c801b3163f331212bf00"
},
{
"path": "default/ui-tour.conf",
"hash": "9adafad611a6408b1448e300f9c33d9f085c4c65c2a6c7d943e948ed4a4c13c9"
},
{
"path": "default/web.conf",
"hash": "5f7f8165052a710dadd4c8a3ee3575027bf3ec9c19a8673526b4f23725f01e41"
},
{
"path": "metadata/default.meta",
"hash": "da00a88bf168a3f7079ee944d539511865d3e704d8be37ceb0027217955f7649"
},
{
"path": "static/appIcon.png",
"hash": "7e2aa1f79791147b9390a927d5c90eda59147c97b127968c165497e152470066"
},
{
"path": "static/appIconAlt.png",
"hash": "7e2aa1f79791147b9390a927d5c90eda59147c97b127968c165497e152470066"
},
{
"path": "static/appIconAlt_2x.png",
"hash": "ab60db107ac936dc61e74632c3db46797d265b32410be3631c21cdfef5cfd33b"
},
{
"path": "static/appIcon_2x.png",
"hash": "ab60db107ac936dc61e74632c3db46797d265b32410be3631c21cdfef5cfd33b"
},
{
"path": "static/appLogo.png",
"hash": "0f6bf549bed7bdabe188535cd756399d49fa6834a53670c20627466049952973"
},
{
"path": "static/appLogo_2x.png",
"hash": "997037f671cb741a1c55f122a74188c0124ed9c4b820e731b93bb62e58a15e83"
}
]
},
"products": [
{
"platform": "splunk",
"product": "enterprise",
"versions": [
"7.0",
"7.1",
"7.2",
"7.3",
"8.0",
"8.1",
"8.2",
"9.0"
],
"architectures": [
"x86_64"
],
"operatingSystems": [
"windows",
"linux",
"macos",
"freebsd",
"solaris",
"aix"
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Loading…
Cancel
Save