├── .gitignore ├── public ├── less │ └── main.less └── logo_hack.js ├── package.json ├── LICENSE ├── index.js ├── README.md ├── .eslintrc └── __gulpfile.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | npm-debug.log 3 | .DS_Store 4 | build/* 5 | target/* 6 | -------------------------------------------------------------------------------- /public/less/main.less: -------------------------------------------------------------------------------- 1 | 2 | .logo { 3 | display: none !important; 4 | } 5 | 6 | .logo-small { 7 | display: none !important; 8 | } 9 | -------------------------------------------------------------------------------- /public/logo_hack.js: -------------------------------------------------------------------------------- 1 | import chrome from 'ui/chrome'; 2 | import 'plugins/kibrand/less/main.less'; 3 | import uiModules from 'ui/modules'; 4 | 5 | uiModules.get('kibana', []) 6 | .config(function() { 7 | let config = chrome.getInjected('brandConfig', {}); 8 | if (config.logourl){ 9 | chrome 10 | .setBrand({ 11 | 'logo': 'url('+config.logourl+') left no-repeat', 12 | 'smallLogo': 'url('+config.logourl+') left no-repeat' 13 | }) 14 | } else { 15 | chrome 16 | .setBrand({ 17 | 'title': config.name ? config.name : "" 18 | }) 19 | 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kibrand", 3 | "version": "0.4.6", 4 | "description": "Kibana Branding Plugin", 5 | "main": "gulpfile.js", 6 | "scripts": { 7 | "start": "gulp --gulpfile __gulpfile.js dev", 8 | "build": "gulp --gulpfile __gulpfile.js build", 9 | "package": "gulp --gulpfile __gulpfile.js package", 10 | "test": "gulp --gulpfile __gulpfile.js test", 11 | "archive": "tar cfz ./kibrand-latest.tar.gz --exclude .git --exclude .gitignore --exclude kibrand-latest.tar.gz --exclude node_modules ./* && ls -alF kibrand*" 12 | }, 13 | "devDependencies": { 14 | "babel-eslint": "^4.1.8", 15 | "babel-preset-es2015": "^6.5.0", 16 | "babel-register": "^6.5.1", 17 | "bluebird": "^3.2.2", 18 | "del": "^2.2.0", 19 | "eslint": "^1.10.3", 20 | "eslint-plugin-mocha": "^1.1.0", 21 | "gulp": "^3.9.1", 22 | "gulp-eslint": "^1.1.1", 23 | "gulp-gzip": "^1.2.0", 24 | "gulp-tar": "^1.8.0", 25 | "gulp-util": "^3.0.7", 26 | "lodash": "^4.3.0", 27 | "mkdirp": "^0.5.1", 28 | "rsync": "^0.4.0" 29 | }, 30 | "dependencies": { 31 | "arrive": "^2.3.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Lorenzo Mangani 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (kibana) { 2 | 3 | var brand; 4 | try { 5 | brand = process.env.BRAND; 6 | } catch(err){ 7 | brand = ""; 8 | } 9 | var logourl; 10 | try { 11 | logourl = process.env.LOGOURL; 12 | } catch(err){ 13 | logourl = ""; 14 | } 15 | var cssless; 16 | try { 17 | cssless = process.env.CSSLESS; 18 | } catch(err){ 19 | cssless = ""; 20 | } 21 | 22 | return new kibana.Plugin({ 23 | id: 'kibrand', 24 | uiExports: { 25 | hacks: [ 26 | 'plugins/kibrand/logo_hack' 27 | ], 28 | injectDefaultVars(server, options) { 29 | let config = server.config(); 30 | return { 31 | brandConfig: { 32 | name: config.get('kibrand.name') || brand, 33 | logourl: config.get('kibrand.logourl') || logourl, 34 | cssless: config.get('kibrand.cssless') || cssless 35 | } 36 | }; 37 | } 38 | }, 39 | config(Joi) { 40 | return Joi.object().keys({ 41 | enabled: Joi.boolean().default(true), 42 | logourl: Joi.string().default(logourl), 43 | cssless: Joi.string().default(cssless), 44 | name: Joi.string().default(brand) 45 | }).default(); 46 | } 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KiBrand 2 | Kibana Plugin for Logo Neutralization 3 | 4 | 5 | 6 | -------- 7 | #### Requirements 8 | 9 | * Kibana 4.6+ 10 | 11 | 12 | ### Installation 13 | ``` 14 | bin/kibana plugin --install kibrand -u https://github.com/elasticfence/kibrand/archive/master.tar.gz 15 | ``` 16 | 17 | #### Configuration 18 | Add your custom branding preferences to ```config/kibana.yml``` 19 | ``` 20 | kibrand.enabled: true 21 | kibrand.name: "NULL" 22 | # kibrand.logourl: "http://127.0.0.2/some/logo.svg" 23 | 24 | ``` 25 | #### Alternative Runtime Usage 26 | * Custom Brand 27 | ``` 28 | BRAND="NULL" bin/kibana 29 | ``` 30 | 31 | * Custom Logo __(local svg)__ 32 | ``` 33 | LOGOURL="/bundles/src/ui/public/images/kibana.svg" bin/kibana 34 | ``` 35 | * Custom Logo __(remote svg)__ 36 | ``` 37 | LOGOURL="http://127.0.0.2/some/logo.svg" bin/kibana 38 | ``` 39 | 40 | #### LESS Override 41 | Optional custom LESS rules can be added in ```/etc/kibrand.less``` 42 | 43 | -------- 44 | 45 | #### FAQ 46 | 47 | * _Q_: I did not add any settings, and Logo and Brands are gone! 48 | * _A_: Correct. No values nullify top bar branding. 49 | 50 | * _Q_: I set a logo and now the brand name is gone! 51 | * _A_: Correct. Once a logo is set, the brand will only be presented at small widths. 52 | 53 | * _Q_: Is this plugin compatible with Kibana 5.0? 54 | * _A_: Likely not yet due to changes in K5 - if you are a Kibana 5 user please provide us feedback 55 | 56 | * _Q_: I installed the plugin and it caused issue X 57 | * _A_: Please immediately open an issue on our tracker and provide full kibana error logs 58 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | parser: babel-eslint 3 | 4 | plugins: 5 | - mocha 6 | 7 | env: 8 | es6: true 9 | amd: true 10 | node: true 11 | mocha: true 12 | browser: true 13 | 14 | 15 | rules: 16 | block-scoped-var: 2 17 | camelcase: [ 2, { properties: never } ] 18 | comma-dangle: 0 19 | comma-style: [ 2, last ] 20 | consistent-return: 0 21 | curly: [ 2, multi-line ] 22 | dot-location: [ 2, property ] 23 | dot-notation: [ 2, { allowKeywords: true } ] 24 | eqeqeq: [ 2, allow-null ] 25 | guard-for-in: 2 26 | indent: [ 2, 2, { SwitchCase: 1 } ] 27 | key-spacing: [ 0, { align: value } ] 28 | max-len: [ 2, 140, 2, { ignoreComments: true, ignoreUrls: true } ] 29 | new-cap: [ 2, { capIsNewExceptions: [ Private ] } ] 30 | no-bitwise: 0 31 | no-caller: 2 32 | no-cond-assign: 0 33 | no-debugger: 2 34 | no-empty: 2 35 | no-eval: 2 36 | no-extend-native: 2 37 | no-extra-parens: 0 38 | no-irregular-whitespace: 2 39 | no-iterator: 2 40 | no-loop-func: 2 41 | no-multi-spaces: 0 42 | no-multi-str: 2 43 | no-nested-ternary: 2 44 | no-new: 0 45 | no-path-concat: 0 46 | no-proto: 2 47 | no-return-assign: 0 48 | no-script-url: 2 49 | no-sequences: 2 50 | no-shadow: 0 51 | no-trailing-spaces: 2 52 | no-undef: 2 53 | no-underscore-dangle: 0 54 | no-unused-expressions: 0 55 | no-unused-vars: 0 56 | no-use-before-define: [ 2, nofunc ] 57 | no-with: 2 58 | one-var: [ 2, never ] 59 | quotes: [ 2, single ] 60 | semi-spacing: [ 2, { before: false, after: true } ] 61 | semi: [ 2, always ] 62 | space-after-keywords: [ 2, always ] 63 | space-before-blocks: [ 2, always ] 64 | space-before-function-paren: [ 2, { anonymous: always, named: never } ] 65 | space-in-parens: [ 2, never ] 66 | space-infix-ops: [ 2, { int32Hint: false } ] 67 | space-return-throw-case: [ 2 ] 68 | space-unary-ops: [ 2 ] 69 | strict: [ 2, never ] 70 | valid-typeof: 2 71 | wrap-iife: [ 2, outside ] 72 | yoda: 0 73 | 74 | mocha/no-exclusive-tests: 2 75 | mocha/handle-done-callback: 2 76 | -------------------------------------------------------------------------------- /__gulpfile.js: -------------------------------------------------------------------------------- 1 | require('babel-register')({ 2 | presets: ['es2015'] 3 | }); 4 | 5 | var gulp = require('gulp'); 6 | var _ = require('lodash'); 7 | var path = require('path'); 8 | var gutil = require('gulp-util'); 9 | var mkdirp = require('mkdirp'); 10 | var Rsync = require('rsync'); 11 | var Promise = require('bluebird'); 12 | var eslint = require('gulp-eslint'); 13 | var del = require('del'); 14 | var tar = require('gulp-tar'); 15 | var gzip = require('gulp-gzip'); 16 | var fs = require('fs'); 17 | 18 | var pkg = require('./package.json'); 19 | var packageName = pkg.name + '-' + pkg.version; 20 | 21 | // relative location of Kibana install 22 | var pathToKibana = '../../kibana'; 23 | 24 | var buildDir = path.resolve(__dirname, 'build'); 25 | var targetDir = path.resolve(__dirname, 'target'); 26 | var buildTarget = path.resolve(buildDir, pkg.name); 27 | var kibanaPluginDir = path.resolve(__dirname, pathToKibana, 'installedPlugins', pkg.name); 28 | 29 | var include = [ 30 | 'package.json', 31 | 'index.js', 32 | 'node_modules', 33 | 'public', 34 | 'webpackShims', 35 | 'server' 36 | ]; 37 | 38 | var exclude = [ 39 | 'gulpfile.js', 40 | '.eslintrc' 41 | ]; 42 | 43 | Object.keys(pkg.devDependencies).forEach(function (name) { 44 | exclude.push(path.join('node_modules', name)); 45 | }); 46 | 47 | function syncPluginTo(dest, done) { 48 | mkdirp(dest, function (err) { 49 | if (err) return done(err); 50 | 51 | var source = path.resolve(__dirname) + '/'; 52 | var rsync = new Rsync(); 53 | 54 | rsync.source(source) 55 | .destination(dest) 56 | .flags('uav') 57 | .recursive(true) 58 | .set('delete') 59 | .include(include) 60 | .exclude(exclude) 61 | .output(function (data) { 62 | process.stdout.write(data.toString('utf8')); 63 | }); 64 | 65 | rsync.execute(function (err) { 66 | if (err) { 67 | console.log(err); 68 | return done(err); 69 | } 70 | done(); 71 | }); 72 | }); 73 | } 74 | 75 | gulp.task('sync', function (done) { 76 | syncPluginTo(kibanaPluginDir, done); 77 | }); 78 | 79 | gulp.task('lint', function (done) { 80 | var filePaths = [ 81 | 'gulpfile.js', 82 | 'server/**/*.js', 83 | 'public/**/*.js', 84 | 'public/**/*.jsx', 85 | ]; 86 | 87 | return gulp.src(filePaths) 88 | // eslint() attaches the lint output to the eslint property 89 | // of the file object so it can be used by other modules. 90 | .pipe(eslint()) 91 | // eslint.format() outputs the lint results to the console. 92 | // Alternatively use eslint.formatEach() (see Docs). 93 | .pipe(eslint.formatEach()) 94 | // To have the process exit with an error code (1) on 95 | // lint error, return the stream and pipe to failOnError last. 96 | .pipe(eslint.failOnError()); 97 | }); 98 | 99 | gulp.task('test', ['lint'], function () { 100 | gutil.log(gutil.colors.red('Nothing to test...')); 101 | }); 102 | 103 | gulp.task('clean', function () { 104 | return del([buildDir, targetDir]); 105 | }); 106 | 107 | gulp.task('build', ['clean'], function (done) { 108 | syncPluginTo(buildTarget, done); 109 | }); 110 | 111 | gulp.task('package', ['build'], function (done) { 112 | return gulp.src(path.join(buildDir, '**', '*')) 113 | .pipe(tar(packageName + '.tar')) 114 | .pipe(gzip()) 115 | .pipe(gulp.dest(targetDir)); 116 | }); 117 | 118 | gulp.task('dev', ['sync'], function (done) { 119 | gulp.watch(['package.json', 'index.js', 'public/**/*', 'server/**/*'], ['sync', 'lint']); 120 | }); 121 | 122 | 123 | --------------------------------------------------------------------------------