You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by sm...@apache.org on 2020/02/28 10:03:19 UTC

[knox] branch master updated: KNOX-2226 - Add home page to Knox (#263)

This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 5eedc61  KNOX-2226 - Add home page to Knox (#263)
5eedc61 is described below

commit 5eedc61070fb036db8e6c705416e9b71add43b27
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Fri Feb 28 11:03:09 2020 +0100

    KNOX-2226 - Add home page to Knox (#263)
---
 gateway-admin-ui/admin-ui/assets/vkbeautify.js     | 375 ---------------------
 gateway-admin-ui/package-lock.json                 |   5 +
 gateway-admin-ui/package.json                      |   1 +
 gateway-admin-ui/pom.xml                           |   5 -
 gateway-applications/pom.xml                       |  12 +
 .../jwt/filter/SSOCookieFederationFilter.java      |  14 +-
 gateway-release/home/conf/topologies/metadata.xml  |  64 ++++
 gateway-release/pom.xml                            |  17 +
 gateway-release/src/assembly.xml                   |   7 +
 .../org/apache/knox/gateway/GatewayServer.java     |  35 ++
 .../gateway/config/impl/GatewayConfigImpl.java     |   9 +
 .../knox/gateway/service/definition/Metadata.java  |  67 ++++
 .../service/definition/ServiceDefinition.java      |  11 +
 .../resources/services/ambari/0.2.2.0/service.xml  |   6 +
 .../resources/services/ambari/2.2.0/service.xml    |   6 +
 .../resources/services/ambariui/2.2.0/service.xml  |   7 +
 .../services/atlas-api/0.1.2.0/service.xml         |   7 +-
 .../resources/services/atlas-api/0.8.0/service.xml |   6 +
 .../resources/services/atlas-api/2.0.0/service.xml |   6 +
 .../resources/services/atlas/0.1.2.0/service.xml   |  10 +-
 .../resources/services/atlas/0.8.0/service.xml     |   8 +-
 .../resources/services/atlas/2.0.0/service.xml     |   7 +
 .../resources/services/avatica/1.9.0/service.xml   |   7 +
 .../resources/services/cm-api/1.0.0/service.xml    |   6 +
 .../resources/services/cm-ui/1.0.0/rewrite.xml     |  33 ++
 .../resources/services/cm-ui/1.0.0/service.xml     |  62 ++++
 .../resources/services/datanode/1.0.0/service.xml  |   6 +
 .../services/druid-broker/0.0.1/service.xml        |  10 +-
 .../druid-coordinator-ui/0.0.1/service.xml         |   6 +
 .../services/druid-coordinator/0.0.1/service.xml   |  10 +-
 .../services/druid-overlord-ui/0.0.1/service.xml   |   8 +-
 .../services/druid-overlord/0.0.1/service.xml      |   7 +
 .../services/druid-router/0.0.1/service.xml        |   6 +
 .../resources/services/hbase/0.98.0/service.xml    |   6 +
 .../resources/services/hbaseui/1.1.0/service.xml   |   8 +
 .../resources/services/hbaseui/2.1.0/service.xml   |   8 +
 .../resources/services/hdfsui/2.7.0/service.xml    |   6 +
 .../resources/services/hdfsui/3.0.0/service.xml    |   6 +
 .../resources/services/hive/0.13.0/service.xml     |   6 +
 .../main/resources/services/hue/1.0.0/service.xml  |   6 +
 .../resources/services/impala/1.0.0/service.xml    |   8 +
 .../resources/services/impalaui/1.0.0/service.xml  |   6 +
 .../services/jobhistoryui/2.7.0/service.xml        |   6 +
 .../resources/services/kafka/0.10.0/service.xml    |   9 +
 .../resources/services/kuduui/1.0.0/service.xml    |   6 +
 .../main/resources/services/livy/0.4.0/service.xml |   6 +
 .../resources/services/logsearch/0.5.0/service.xml |   8 +-
 .../services/nifi-registry/0.5.0/service.xml       |   6 +
 .../main/resources/services/nifi/1.4.0/service.xml |   6 +
 .../services/nodemanagerui/2.7.1/service.xml       |   6 +
 .../resources/services/oozie/4.0.0/service.xml     |   6 +
 .../resources/services/oozieui/4.2.0/service.xml   |   6 +
 .../resources/services/ranger/0.1.0.0/service.xml  |   7 +
 .../resources/services/ranger/0.5.0/service.xml    |   7 +
 .../resources/services/ranger/1.0.0/service.xml    |   7 +
 .../resources/services/rangerui/0.5.0/service.xml  |   6 +
 .../resources/services/rangerui/1.0.0/service.xml  |   6 +
 .../main/resources/services/solr/5.5.0/service.xml |   6 +
 .../main/resources/services/solr/6.0.0/service.xml |   6 +
 .../services/sparkhistoryui/1.4.0/service.xml      |   6 +
 .../services/sparkhistoryui/2.3.0/service.xml      |   6 +
 .../services/sparkthriftui/2.1.0/service.xml       |   6 +
 .../services/storm-logviewer/0.9.3/service.xml     |   7 +
 .../resources/services/storm/0.9.3/service.xml     |   7 +
 .../resources/services/webhcat/0.13.0/service.xml  |   6 +
 .../resources/services/webhdfs/2.4.0/service.xml   |   6 +
 .../resources/services/yarn-rm/2.5.0/service.xml   |   6 +
 .../resources/services/yarnui/2.7.0/service.xml    |   6 +
 .../resources/services/yarnuiv2/3.0.0/service.xml  |   6 +
 .../services/zeppelinui/0.6.0/service.xml          |   6 +
 .../services/zeppelinui/0.8.0/service.xml          |   6 +
 .../services/zeppelinui/0.8.1/service.xml          |   6 +
 .../services/zeppelinws/0.6.0/service.xml          |   6 +
 .../services/zeppelinws/0.8.1/service.xml          |   6 +
 gateway-service-metadata/pom.xml                   |  70 ++++
 .../service/metadata/GeneralProxyInformation.java  |  59 ++++
 .../GeneralProxyInformationMarshaller.java         |  89 +++++
 .../service/metadata/KnoxMetadataResource.java     | 232 +++++++++++++
 .../KnoxMetadataServiceDeploymentContributor.java  |  44 +++
 .../service/metadata/MetadataServiceMessages.java  |  34 ++
 .../gateway/service/metadata/ServiceModel.java     | 121 +++++++
 .../service/metadata/TopologyInformation.java      |  64 ++++
 .../metadata/TopologyInformationWrapper.java       |  48 +++
 .../TopologyInformationWrapperMarshaller.java      |  89 +++++
 ...nox.gateway.deploy.ServiceDeploymentContributor |  18 +
 .../apache/knox/gateway/config/GatewayConfig.java  |   5 +
 .../org/apache/knox/gateway/GatewayTestConfig.java |   5 +
 .../apache/knox/gateway/GatewayAppFuncTest.java    |  16 +-
 .../apache/knox/gateway/GatewayDeployFuncTest.java |   6 +-
 knox-homepage-ui/.gitignore                        |  12 +
 knox-homepage-ui/angular-cli.json                  |  54 +++
 knox-homepage-ui/homepage/app/app.module.ts        |  42 +++
 .../general.proxy.information.component.html       |  57 ++++
 .../general.proxy.information.component.ts         |  69 ++++
 .../general.proxy.information.ts                   |  22 ++
 knox-homepage-ui/homepage/app/homepage.service.ts  |  85 +++++
 .../homepage/app/topologies/service.ts             |  26 ++
 .../topologies/topology.information.component.html |  84 +++++
 .../topologies/topology.information.component.ts   |  50 +++
 .../app/topologies/topology.information.ts         |  23 ++
 knox-homepage-ui/homepage/assets/.gitkeep          |  17 +
 .../homepage/assets/knox-logo-transparent.gif      | Bin 0 -> 19703 bytes
 knox-homepage-ui/homepage/assets/sticky-footer.css |  42 +++
 .../homepage/environments/environment.prod.ts      |  19 ++
 .../homepage/environments/environment.ts           |  24 ++
 knox-homepage-ui/homepage/favicon.ico              | Bin 0 -> 1082 bytes
 knox-homepage-ui/homepage/index.html               |  51 +++
 knox-homepage-ui/homepage/main.ts                  |  28 ++
 knox-homepage-ui/homepage/polyfills.ts             |  35 ++
 knox-homepage-ui/homepage/styles.css               |  27 ++
 knox-homepage-ui/homepage/tsconfig.json            |  21 ++
 knox-homepage-ui/npm                               |  20 ++
 .../package-lock.json                              | 110 ++----
 .../package.json                                   |  17 +-
 {gateway-admin-ui => knox-homepage-ui}/pom.xml     |  42 ++-
 knox-homepage-ui/proxy.conf.json                   |   8 +
 .../src/main/webapp/%2F/WEB-INF/gateway.xml        |  77 +++++
 .../src/main/webapp/%2F/WEB-INF/web.xml            |  35 ++
 .../src/main/webapp/%2Fhome/WEB-INF/gateway.xml    | 118 +++++++
 .../src/main/webapp/%2Fhome/WEB-INF/web.xml        |  35 ++
 knox-homepage-ui/tslint.json                       |  94 ++++++
 pom.xml                                            |  25 ++
 122 files changed, 2866 insertions(+), 511 deletions(-)

diff --git a/gateway-admin-ui/admin-ui/assets/vkbeautify.js b/gateway-admin-ui/admin-ui/assets/vkbeautify.js
deleted file mode 100644
index 60213d0..0000000
--- a/gateway-admin-ui/admin-ui/assets/vkbeautify.js
+++ /dev/null
@@ -1,375 +0,0 @@
-/**
- * vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.
- *
- * Version - 0.99.00.beta
- * Copyright (c) 2012 Vadim Kiryukhin
- * vkiryukhin @ gmail.com
- * http://www.eslinstructor.net/vkbeautify/
- *
- * MIT license:
- *   http://www.opensource.org/licenses/mit-license.php
- *
- *   Pretty print
- *
- *        vkbeautify.xml(text [,indent_pattern]);
- *        vkbeautify.json(text [,indent_pattern]);
- *        vkbeautify.css(text [,indent_pattern]);
- *        vkbeautify.sql(text [,indent_pattern]);
- *
- *        @text - String; text to beatufy;
- *        @indent_pattern - Integer | String;
- *                Integer:  number of white spaces;
- *                String:   character string to visualize indentation ( can also be a set of white spaces )
- *   Minify
- *
- *        vkbeautify.xmlmin(text [,preserve_comments]);
- *        vkbeautify.jsonmin(text);
- *        vkbeautify.cssmin(text [,preserve_comments]);
- *        vkbeautify.sqlmin(text);
- *
- *        @text - String; text to minify;
- *        @preserve_comments - Bool; [optional];
- *                Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )
- *
- *   Examples:
- *        vkbeautify.xml(text); // pretty print XML
- *        vkbeautify.json(text, 4 ); // pretty print JSON
- *        vkbeautify.css(text, '. . . .'); // pretty print CSS
- *        vkbeautify.sql(text, '----'); // pretty print SQL
- *
- *        vkbeautify.xmlmin(text, true);// minify XML, preserve comments
- *        vkbeautify.jsonmin(text);// minify JSON
- *        vkbeautify.cssmin(text);// minify CSS, remove comments ( default )
- *        vkbeautify.sqlmin(text);// minify SQL
- *
- */
-
-(function () {
-
-    function createShiftArr(step) {
-
-        var space = '    ';
-
-        if (isNaN(parseInt(step))) {  // argument is string
-            space = step;
-        } else { // argument is integer
-            switch (step) {
-                case 1:
-                    space = ' ';
-                    break;
-                case 2:
-                    space = '  ';
-                    break;
-                case 3:
-                    space = '   ';
-                    break;
-                case 4:
-                    space = '    ';
-                    break;
-                case 5:
-                    space = '     ';
-                    break;
-                case 6:
-                    space = '      ';
-                    break;
-                case 7:
-                    space = '       ';
-                    break;
-                case 8:
-                    space = '        ';
-                    break;
-                case 9:
-                    space = '         ';
-                    break;
-                case 10:
-                    space = '          ';
-                    break;
-                case 11:
-                    space = '           ';
-                    break;
-                case 12:
-                    space = '            ';
-                    break;
-            }
-        }
-
-        var shift = ['\n']; // array of shifts
-        for (ix = 0; ix < 100; ix++) {
-            shift.push(shift[ix] + space);
-        }
-        return shift;
-    }
-
-    function vkbeautify() {
-        this.step = '\t'; // 4 spaces
-        this.shift = createShiftArr(this.step);
-    };
-
-    vkbeautify.prototype.xml = function (text, step) {
-
-        var ar = text.replace(/>\s{0,}</g, "><")
-                .replace(/</g, "~::~<")
-                .replace(/\s*xmlns\:/g, "~::~xmlns:")
-                .replace(/\s*xmlns\=/g, "~::~xmlns=")
-                .split('~::~'),
-            len = ar.length,
-            inComment = false,
-            deep = 0,
-            str = '',
-            ix = 0,
-            shift = step ? createShiftArr(step) : this.shift;
-
-        for (ix = 0; ix < len; ix++) {
-            // start comment or <![CDATA[...]]> or <!DOCTYPE //
-            if (ar[ix].search(/<!/) > -1) {
-                str += shift[deep] + ar[ix];
-                inComment = true;
-                // end comment  or <![CDATA[...]]> //
-                if (ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1) {
-                    inComment = false;
-                }
-            } else
-            // end comment  or <![CDATA[...]]> //
-            if (ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) {
-                str += ar[ix];
-                inComment = false;
-            } else
-            // <elm></elm> //
-            if (/^<\w/.exec(ar[ix - 1]) && /^<\/\w/.exec(ar[ix]) &&
-                /^<[\w:\-\.\,]+/.exec(ar[ix - 1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/', '')) {
-                str += ar[ix];
-                if (!inComment) deep--;
-            } else
-            // <elm> //
-            if (ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1) {
-                str = !inComment ? str += shift[deep++] + ar[ix] : str += ar[ix];
-            } else
-            // <elm>...</elm> //
-            if (ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) {
-                str = !inComment ? str += shift[deep] + ar[ix] : str += ar[ix];
-            } else
-            // </elm> //
-            if (ar[ix].search(/<\//) > -1) {
-                str = !inComment ? str += shift[--deep] + ar[ix] : str += ar[ix];
-            } else
-            // <elm/> //
-            if (ar[ix].search(/\/>/) > -1) {
-                str = !inComment ? str += shift[deep] + ar[ix] : str += ar[ix];
-            } else
-            // <? xml ... ?> //
-            if (ar[ix].search(/<\?/) > -1) {
-                str += shift[deep] + ar[ix];
-            } else
-            // xmlns //
-            if (ar[ix].search(/xmlns\:/) > -1 || ar[ix].search(/xmlns\=/) > -1) {
-                str += shift[deep] + ar[ix];
-            } else {
-                str += ar[ix];
-            }
-        }
-
-        return (str[0] == '\n') ? str.slice(1) : str;
-    }
-
-    vkbeautify.prototype.json = function (text, step) {
-
-        var step = step ? step : this.step;
-
-        if (typeof JSON === 'undefined') return text;
-
-        if (typeof text === "string") return JSON.stringify(JSON.parse(text), null, step);
-        if (typeof text === "object") return JSON.stringify(text, null, step);
-
-        return text; // text is not string nor object
-    }
-
-    vkbeautify.prototype.css = function (text, step) {
-
-        var ar = text.replace(/\s{1,}/g, ' ')
-                .replace(/\{/g, "{~::~")
-                .replace(/\}/g, "~::~}~::~")
-                .replace(/\;/g, ";~::~")
-                .replace(/\/\*/g, "~::~/*")
-                .replace(/\*\//g, "*/~::~")
-                .replace(/~::~\s{0,}~::~/g, "~::~")
-                .split('~::~'),
-            len = ar.length,
-            deep = 0,
-            str = '',
-            ix = 0,
-            shift = step ? createShiftArr(step) : this.shift;
-
-        for (ix = 0; ix < len; ix++) {
-
-            if (/\{/.exec(ar[ix])) {
-                str += shift[deep++] + ar[ix];
-            } else if (/\}/.exec(ar[ix])) {
-                str += shift[--deep] + ar[ix];
-            } else if (/\*\\/.exec(ar[ix])) {
-                str += shift[deep] + ar[ix];
-            } else {
-                str += shift[deep] + ar[ix];
-            }
-        }
-        return str.replace(/^\n{1,}/, '');
-    }
-
-//----------------------------------------------------------------------------
-
-    function isSubquery(str, parenthesisLevel) {
-        return parenthesisLevel - (str.replace(/\(/g, '').length - str.replace(/\)/g, '').length)
-    }
-
-    function split_sql(str, tab) {
-
-        return str.replace(/\s{1,}/g, " ")
-
-            .replace(/ AND /ig, "~::~" + tab + tab + "AND ")
-            .replace(/ BETWEEN /ig, "~::~" + tab + "BETWEEN ")
-            .replace(/ CASE /ig, "~::~" + tab + "CASE ")
-            .replace(/ ELSE /ig, "~::~" + tab + "ELSE ")
-            .replace(/ END /ig, "~::~" + tab + "END ")
-            .replace(/ FROM /ig, "~::~FROM ")
-            .replace(/ GROUP\s{1,}BY/ig, "~::~GROUP BY ")
-            .replace(/ HAVING /ig, "~::~HAVING ")
-            //.replace(/ SET /ig," SET~::~")
-            .replace(/ IN /ig, " IN ")
-
-            .replace(/ JOIN /ig, "~::~JOIN ")
-            .replace(/ CROSS~::~{1,}JOIN /ig, "~::~CROSS JOIN ")
-            .replace(/ INNER~::~{1,}JOIN /ig, "~::~INNER JOIN ")
-            .replace(/ LEFT~::~{1,}JOIN /ig, "~::~LEFT JOIN ")
-            .replace(/ RIGHT~::~{1,}JOIN /ig, "~::~RIGHT JOIN ")
-
-            .replace(/ ON /ig, "~::~" + tab + "ON ")
-            .replace(/ OR /ig, "~::~" + tab + tab + "OR ")
-            .replace(/ ORDER\s{1,}BY/ig, "~::~ORDER BY ")
-            .replace(/ OVER /ig, "~::~" + tab + "OVER ")
-
-            .replace(/\(\s{0,}SELECT /ig, "~::~(SELECT ")
-            .replace(/\)\s{0,}SELECT /ig, ")~::~SELECT ")
-
-            .replace(/ THEN /ig, " THEN~::~" + tab + "")
-            .replace(/ UNION /ig, "~::~UNION~::~")
-            .replace(/ USING /ig, "~::~USING ")
-            .replace(/ WHEN /ig, "~::~" + tab + "WHEN ")
-            .replace(/ WHERE /ig, "~::~WHERE ")
-            .replace(/ WITH /ig, "~::~WITH ")
-
-            //.replace(/\,\s{0,}\(/ig,",~::~( ")
-            //.replace(/\,/ig,",~::~"+tab+tab+"")
-
-            .replace(/ ALL /ig, " ALL ")
-            .replace(/ AS /ig, " AS ")
-            .replace(/ ASC /ig, " ASC ")
-            .replace(/ DESC /ig, " DESC ")
-            .replace(/ DISTINCT /ig, " DISTINCT ")
-            .replace(/ EXISTS /ig, " EXISTS ")
-            .replace(/ NOT /ig, " NOT ")
-            .replace(/ NULL /ig, " NULL ")
-            .replace(/ LIKE /ig, " LIKE ")
-            .replace(/\s{0,}SELECT /ig, "SELECT ")
-            .replace(/\s{0,}UPDATE /ig, "UPDATE ")
-            .replace(/ SET /ig, " SET ")
-
-            .replace(/~::~{1,}/g, "~::~")
-            .split('~::~');
-    }
-
-    vkbeautify.prototype.sql = function (text, step) {
-
-        var ar_by_quote = text.replace(/\s{1,}/g, " ")
-                .replace(/\'/ig, "~::~\'")
-                .split('~::~'),
-            len = ar_by_quote.length,
-            ar = [],
-            deep = 0,
-            tab = this.step,//+this.step,
-            inComment = true,
-            inQuote = false,
-            parenthesisLevel = 0,
-            str = '',
-            ix = 0,
-            shift = step ? createShiftArr(step) : this.shift;
-        ;
-
-        for (ix = 0; ix < len; ix++) {
-            if (ix % 2) {
-                ar = ar.concat(ar_by_quote[ix]);
-            } else {
-                ar = ar.concat(split_sql(ar_by_quote[ix], tab));
-            }
-        }
-
-        len = ar.length;
-        for (ix = 0; ix < len; ix++) {
-
-            parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);
-
-            if (/\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
-                ar[ix] = ar[ix].replace(/\,/g, ",\n" + tab + tab + "")
-            }
-
-            if (/\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix])) {
-                ar[ix] = ar[ix].replace(/\,/g, ",\n" + tab + tab + "")
-            }
-
-            if (/\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
-                deep++;
-                str += shift[deep] + ar[ix];
-            } else if (/\'/.exec(ar[ix])) {
-                if (parenthesisLevel < 1 && deep) {
-                    deep--;
-                }
-                str += ar[ix];
-            } else {
-                str += shift[deep] + ar[ix];
-                if (parenthesisLevel < 1 && deep) {
-                    deep--;
-                }
-            }
-            var junk = 0;
-        }
-
-        str = str.replace(/^\n{1,}/, '').replace(/\n{1,}/g, "\n");
-        return str;
-    }
-
-
-    vkbeautify.prototype.xmlmin = function (text, preserveComments) {
-
-        var str = preserveComments ? text
-            : text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g, "")
-                .replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns');
-        return str.replace(/>\s{0,}</g, "><");
-    }
-
-    vkbeautify.prototype.jsonmin = function (text) {
-
-        if (typeof JSON === 'undefined') return text;
-
-        return JSON.stringify(JSON.parse(text), null, 0);
-
-    }
-
-    vkbeautify.prototype.cssmin = function (text, preserveComments) {
-
-        var str = preserveComments ? text
-            : text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g, "");
-
-        return str.replace(/\s{1,}/g, ' ')
-            .replace(/\{\s{1,}/g, "{")
-            .replace(/\}\s{1,}/g, "}")
-            .replace(/\;\s{1,}/g, ";")
-            .replace(/\/\*\s{1,}/g, "/*")
-            .replace(/\*\/\s{1,}/g, "*/");
-    }
-
-    vkbeautify.prototype.sqlmin = function (text) {
-        return text.replace(/\s{1,}/g, " ").replace(/\s{1,}\(/, "(").replace(/\s{1,}\)/, ")");
-    }
-
-    window.vkbeautify = new vkbeautify();
-
-})();
-
diff --git a/gateway-admin-ui/package-lock.json b/gateway-admin-ui/package-lock.json
index 7695dce..3baa0ee 100644
--- a/gateway-admin-ui/package-lock.json
+++ b/gateway-admin-ui/package-lock.json
@@ -8459,6 +8459,11 @@
         }
       }
     },
+    "vkbeautify": {
+      "version": "0.99.3",
+      "resolved": "https://registry.npmjs.org/vkbeautify/-/vkbeautify-0.99.3.tgz",
+      "integrity": "sha512-2ozZEFfmVvQcHWoHLNuiKlUfDKlhh4KGsy54U0UrlLMR1SO+XKAIDqBxtBwHgNrekurlJwE8A9K6L49T78ZQ9Q=="
+    },
     "vlq": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
diff --git a/gateway-admin-ui/package.json b/gateway-admin-ui/package.json
index aaa9b0d..5738504 100644
--- a/gateway-admin-ui/package.json
+++ b/gateway-admin-ui/package.json
@@ -31,6 +31,7 @@
     "rxjs": "^5.5.2",
     "sweetalert": "^2.1.2",
     "ts-helpers": "^1.1.1",
+    "vkbeautify": "^0.99.3",
     "zone.js": "^0.8.29"
   },
   "devDependencies": {
diff --git a/gateway-admin-ui/pom.xml b/gateway-admin-ui/pom.xml
index 4ba1d39..6e202be 100644
--- a/gateway-admin-ui/pom.xml
+++ b/gateway-admin-ui/pom.xml
@@ -29,11 +29,6 @@
     <name>gateway-admin-ui</name>
     <description>The gateway-admin-ui delivered with Knox.</description>
 
-    <properties>
-        <frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version>
-        <nodejs.version>v12.14.1</nodejs.version>
-    </properties>
-
     <build>
         <plugins>
             <plugin>
diff --git a/gateway-applications/pom.xml b/gateway-applications/pom.xml
index c35af85..a5d73c2 100644
--- a/gateway-applications/pom.xml
+++ b/gateway-applications/pom.xml
@@ -34,6 +34,11 @@
             <groupId>org.apache.knox</groupId>
             <artifactId>gateway-admin-ui</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>knox-homepage-ui</artifactId>
+            <type>war</type>
+        </dependency>
     </dependencies>
 
     <build>
@@ -58,6 +63,13 @@
                                     <outputDirectory>${project.build.outputDirectory}/applications</outputDirectory>
                                     <includes>admin-ui/**</includes>
                                 </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.knox</groupId>
+                                    <artifactId>knox-homepage-ui</artifactId>
+                                    <type>war</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.build.outputDirectory}/deployments/homepage</outputDirectory>
+                                </artifactItem>
                             </artifactItems>
                         </configuration>
                     </execution>
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
index 814a5a7..6a37c2f 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
@@ -17,6 +17,7 @@
  */
 package org.apache.knox.gateway.provider.federation.jwt.filter;
 
+import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.provider.federation.jwt.JWTMessages;
 import org.apache.knox.gateway.security.PrimaryPrincipal;
@@ -92,11 +93,22 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter {
     }
 
     // gateway path for deriving an idp url when missing
-    gatewayPath = filterConfig.getInitParameter(GATEWAY_PATH);
+    setGatewayPath(filterConfig);
 
     configureExpectedParameters(filterConfig);
   }
 
+  private void setGatewayPath(FilterConfig filterConfig) {
+    gatewayPath = filterConfig.getInitParameter(GATEWAY_PATH);
+    if (gatewayPath == null || gatewayPath.isEmpty()) {
+      final GatewayConfig gatewayConfig = filterConfig.getServletContext() == null ? null
+          : (GatewayConfig) filterConfig.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+      if (gatewayConfig != null) {
+        gatewayPath = gatewayConfig.getGatewayPath();
+      }
+    }
+  }
+
   @Override
   public void destroy() {
   }
diff --git a/gateway-release/home/conf/topologies/metadata.xml b/gateway-release/home/conf/topologies/metadata.xml
new file mode 100644
index 0000000..f85117b
--- /dev/null
+++ b/gateway-release/home/conf/topologies/metadata.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+-->
+<topology>
+
+    <gateway>
+        <provider>
+            <role>authentication</role>
+            <name>ShiroProvider</name>
+            <enabled>true</enabled>
+            <param>
+                <name>sessionTimeout</name>
+                <value>30</value>
+            </param>
+            <param>
+                <name>main.ldapRealm</name>
+                <value>org.apache.knox.gateway.shirorealm.KnoxLdapRealm</value>
+            </param>
+            <param>
+                <name>main.ldapContextFactory</name>
+                <value>org.apache.knox.gateway.shirorealm.KnoxLdapContextFactory</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.contextFactory</name>
+                <value>$ldapContextFactory</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.userDnTemplate</name>
+                <value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.contextFactory.url</name>
+                <value>ldap://localhost:33389</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.contextFactory.authenticationMechanism</name>
+                <value>simple</value>
+            </param>
+            <param>
+                <name>urls./**</name>
+                <value>authcBasic</value>
+            </param>
+        </provider>
+    </gateway>
+
+    <service>
+        <role>KNOX-METADATA</role>
+    </service>
+
+</topology>
diff --git a/gateway-release/pom.xml b/gateway-release/pom.xml
index 0eefa56..cc634a0 100644
--- a/gateway-release/pom.xml
+++ b/gateway-release/pom.xml
@@ -146,6 +146,14 @@
                                         </artifactItem>
                                         <artifactItem>
                                             <groupId>org.apache.knox</groupId>
+                                            <artifactId>gateway-applications</artifactId>
+                                            <type>jar</type>
+                                            <overWrite>false</overWrite>
+                                            <outputDirectory>${project.build.directory}</outputDirectory>
+                                            <includes>deployments/**/*</includes>
+                                        </artifactItem>
+                                        <artifactItem>
+                                            <groupId>org.apache.knox</groupId>
                                             <artifactId>gateway-shell-samples</artifactId>
                                             <type>jar</type>
                                             <overWrite>false</overWrite>
@@ -433,5 +441,14 @@
             <groupId>org.apache.knox</groupId>
             <artifactId>gateway-cm-integration</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-service-metadata</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>knox-homepage-ui</artifactId>
+            <type>war</type>
+        </dependency>
     </dependencies>
 </project>
diff --git a/gateway-release/src/assembly.xml b/gateway-release/src/assembly.xml
index d509c2e..fa62f6a 100644
--- a/gateway-release/src/assembly.xml
+++ b/gateway-release/src/assembly.xml
@@ -90,6 +90,13 @@
                 <exclude>**/*.bundle.map</exclude>
             </excludes>
         </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/deployments</directory>
+            <outputDirectory>data/deployments</outputDirectory>
+            <includes>
+                <include>**/%2F*/**/*</include>
+            </includes>
+        </fileSet>
     </fileSets>
     <dependencySets>
         <dependencySet>
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
index 58a0e41..958e03d 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
@@ -708,6 +708,8 @@ public class GatewayServer {
     log.monitoringTopologyChangesInDirectory(topologiesDir.getAbsolutePath());
     monitor.startMonitor();
 
+    activateHomeApp();
+
     Runtime.getRuntime().addShutdownHook(new Thread() {
 
       @Override
@@ -923,6 +925,39 @@ public class GatewayServer {
     }
   }
 
+  private synchronized void activateHomeApp() {
+    try {
+      // UI
+      activateHomepageContext("/", "homepage/%2Fhome");
+
+      // API
+      activateHomepageContext("/homepage", "homepage/%2F");
+    } catch (Throwable e) {
+      auditor.audit(Action.DEPLOY, "home", ResourceType.URI, ActionOutcome.FAILURE);
+      log.failedToDeployTopology("home", e);
+    }
+  }
+
+  private void activateHomepageContext(String contextPath, String deploymentFolder) throws Throwable {
+    final WebAppContext context = new WebAppContext();
+    context.setContextPath(contextPath);
+    context.setServer(jetty);
+    SessionCookieConfig sessionCookieConfig = context.getServletContext().getSessionCookieConfig();
+    sessionCookieConfig.setName(KNOXSESSIONCOOKIENAME);
+    final Path homePageDeploymentDir = Paths.get(calculateAbsoluteDeploymentsDir().getAbsolutePath(), deploymentFolder);
+    context.setWar(homePageDeploymentDir.toString());
+    context.setTempDirectory(FileUtils.getFile(homePageDeploymentDir.toFile(), "META-INF", "temp"));
+    context.setErrorHandler(createErrorHandler());
+    context.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
+    context.setWelcomeFiles(new String[] { "index.html" });
+    context.setAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE, config);
+    contexts.addHandler(context);
+    context.start();
+    if (!context.isAvailable()) {
+      throw context.getUnavailableException();
+    }
+  }
+
   private synchronized void internalDeactivateTopology( Topology topology ) {
 
     log.deactivatingTopology( topology.getName() );
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
index b527220..117165a 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
@@ -252,6 +252,9 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
   private static final long KNOX_TOKEN_EVICTION_INTERVAL_DEFAULT = TimeUnit.MINUTES.toSeconds(5);
   private static final long KNOX_TOKEN_EVICTION_GRACE_PERIOD_DEFAULT = TimeUnit.MINUTES.toSeconds(5);
 
+  private static final String KNOX_HOMEPAGE_HIDDEN_TOPOLOGIES =  "knox.homepage.hidden.topologies";
+  private static final Set<String> KNOX_HOMEPAGE_HIDDEN_TOPOLOGIES_DEFAULT = new HashSet<>(Arrays.asList("admin", "manager", "knoxsso", "metadata"));
+
   public GatewayConfigImpl() {
     init();
   }
@@ -1132,4 +1135,10 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
   public long getKnoxTokenEvictionGracePeriod() {
     return getLong(KNOX_TOKEN_EVICTION_GRACE_PERIOD, KNOX_TOKEN_EVICTION_GRACE_PERIOD_DEFAULT);
   }
+
+  @Override
+  public Set<String> getHiddenTopologiesOnHomepage() {
+    final Set<String> hiddenTopologies = new HashSet<>(getStringCollection(KNOX_HOMEPAGE_HIDDEN_TOPOLOGIES));
+    return hiddenTopologies == null || hiddenTopologies.isEmpty() ? KNOX_HOMEPAGE_HIDDEN_TOPOLOGIES_DEFAULT : hiddenTopologies;
+  }
 }
diff --git a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
new file mode 100644
index 0000000..da642f7
--- /dev/null
+++ b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.definition;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "metadata")
+public class Metadata {
+
+  private String type;
+  private String context;
+  private String shortDesc;
+  private String description;
+
+  @XmlElement(name = "type")
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  @XmlElement(name = "context")
+  public String getContext() {
+    return context;
+  }
+
+  public void setContext(String context) {
+    this.context = context;
+  }
+
+  @XmlElement(name = "shortDesc")
+  public String getShortDesc() {
+    return shortDesc;
+  }
+
+  public void setShortDesc(String shortDesc) {
+    this.shortDesc = shortDesc;
+  }
+
+  @XmlElement(name = "description")
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+}
diff --git a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/ServiceDefinition.java b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/ServiceDefinition.java
index 2415f16..4da0976 100644
--- a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/ServiceDefinition.java
+++ b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/ServiceDefinition.java
@@ -33,6 +33,8 @@ public class ServiceDefinition {
 
   private String version;
 
+  private Metadata metadata;
+
   private List<Route> routes;
 
   private List<Policy> policies;
@@ -68,6 +70,15 @@ public class ServiceDefinition {
     this.version = version;
   }
 
+  @XmlElement(name = "metadata")
+  public Metadata getMetadata() {
+    return metadata;
+  }
+
+  public void setMetadata(Metadata metadata) {
+    this.metadata = metadata;
+  }
+
   @XmlElement(name = "route")
   @XmlElementWrapper(name = "routes")
   public List<Route> getRoutes() {
diff --git a/gateway-service-definitions/src/main/resources/services/ambari/0.2.2.0/service.xml b/gateway-service-definitions/src/main/resources/services/ambari/0.2.2.0/service.xml
index be90219..ff9c002 100644
--- a/gateway-service-definitions/src/main/resources/services/ambari/0.2.2.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ambari/0.2.2.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="AMBARI" name="ambari" version="0.2.2.0">
+    <metadata>
+        <type>API</type>
+        <context>/ambari/api</context>
+        <shortDesc>Apache Ambari API</shortDesc>
+        <description>The Ambari API facilitates the management and monitoring of the resources of an Apache Hadoop cluster.</description>
+    </metadata>
     <routes>
         <route path="/ambari/api/v1/**">
             <rewrite apply="AMBARI/ambari/api/outbound" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml b/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
index a7ce77c..05da7ac 100644
--- a/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="AMBARI" name="ambari" version="2.2.0">
+    <metadata>
+        <type>API</type>
+        <context>/ambari/api</context>
+        <shortDesc>Apache Ambari API</shortDesc>
+        <description>The Ambari API facilitates the management and monitoring of the resources of an Apache Hadoop cluster.</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/ambariui/2.2.0/service.xml b/gateway-service-definitions/src/main/resources/services/ambariui/2.2.0/service.xml
index bf77ec9..00a596e 100644
--- a/gateway-service-definitions/src/main/resources/services/ambariui/2.2.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ambariui/2.2.0/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="AMBARIUI" name="ambariui" version="2.2.0">
+    <metadata>
+        <type>UI</type>
+        <context>/ambari</context>
+        <shortDesc>Apache Ambari Web UI</shortDesc>
+        <description>The Apache Ambari project is aimed at making Hadoop management simpler by developing software for provisioning, managing, and monitoring Apache Hadoop clusters. 
+            Ambari provides an intuitive, easy-to-use Hadoop management web UI backed by its RESTful APIs.</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/atlas-api/0.1.2.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas-api/0.1.2.0/service.xml
index 031ca2c..17ae3d8 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas-api/0.1.2.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas-api/0.1.2.0/service.xml
@@ -17,7 +17,12 @@
 
 
 <service role="ATLAS-API" name="atlas-api" version="0.1.2.0">
-
+    <metadata>
+        <type>API</type>
+        <context>/atlas/api</context>
+        <shortDesc>Atlas API</shortDesc>
+        <description>Atlas exposes a variety of REST endpoints to work with types, entities, lineage and data discovery.</description>
+    </metadata>
     <routes>
         <route path="/atlas/api/**"/>
     </routes>
diff --git a/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
index 20662ac..afffe0f 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
@@ -17,6 +17,12 @@
 
 
 <service role="ATLAS-API" name="atlas-api" version="0.8.0">
+    <metadata>
+        <type>API</type>
+        <context>/atlas/api</context>
+        <shortDesc>Atlas API</shortDesc>
+        <description>Atlas exposes a variety of REST endpoints to work with types, entities, lineage and data discovery.</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
index 83aa31a..5ba13d0 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="ATLAS-API" name="atlas-api" version="2.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/atlas/api</context>
+        <shortDesc>Atlas API</shortDesc>
+        <description>Atlas exposes a variety of REST endpoints to work with types, entities, lineage and data discovery.</description>
+    </metadata>
     <routes>
         <route path="/atlas/api/**"/>
     </routes>
diff --git a/gateway-service-definitions/src/main/resources/services/atlas/0.1.2.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas/0.1.2.0/service.xml
index cb7813d..95ea4f0 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas/0.1.2.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas/0.1.2.0/service.xml
@@ -16,8 +16,14 @@
 -->
 
 <service role="ATLAS" name="atlas" version="0.1.2.0">
-    
-<routes>
+    <metadata>
+        <type>UI</type>
+        <context>/atlas</context>
+        <shortDesc>Atlas UI</shortDesc>
+        <description>Apache Atlas provides open metadata management and governance capabilities for organizations to build a catalog of their data assets, 
+            classify and govern these assets and provide collaboration capabilities around these data assets for data scientists, analysts and the data governance team.</description>
+    </metadata>
+	<routes>
 
         <route path="/atlas">
             <rewrite apply="ATLAS/atlas/inbound/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
index 8899248..cd28e1b 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
@@ -16,7 +16,13 @@
 -->
 
 <service role="ATLAS" name="atlas" version="0.8.0">
-
+    <metadata>
+        <type>UI</type>
+        <context>/atlas</context>
+        <shortDesc>Atlas UI</shortDesc>
+        <description>Apache Atlas provides open metadata management and governance capabilities for organizations to build a catalog of their data assets, 
+            classify and govern these assets and provide collaboration capabilities around these data assets for data scientists, analysts and the data governance team.</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/atlas/2.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas/2.0.0/service.xml
index 2566d08..0ee5266 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas/2.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas/2.0.0/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="ATLAS" name="atlas" version="2.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/atlas</context>
+        <shortDesc>Atlas UI</shortDesc>
+        <description>Apache Atlas provides open metadata management and governance capabilities for organizations to build a catalog of their data assets, 
+            classify and govern these assets and provide collaboration capabilities around these data assets for data scientists, analysts and the data governance team.</description>
+    </metadata>
     <routes>
         <route path="/atlas">
             <rewrite apply="ATLAS/atlas/inbound/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/avatica/1.9.0/service.xml b/gateway-service-definitions/src/main/resources/services/avatica/1.9.0/service.xml
index bcd9c73..fe212a9 100644
--- a/gateway-service-definitions/src/main/resources/services/avatica/1.9.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/avatica/1.9.0/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="AVATICA" name="avatica" version="1.9.0">
+    <metadata>
+        <type>API</type>
+        <context>/avatica</context>
+        <shortDesc>Phoenix Query Server</shortDesc>
+        <description>The Phoenix Query Server provides an alternative means for interaction with Phoenix and HBase. Phoenix 4.4 introduces a stand-alone server that exposes Phoenix to “thin” clients. 
+            It is based on the Avatica component of Apache Calcite. Avatica is a framework for building JDBC and ODBC drivers for databases, and an RPC wire protocol.</description>
+    </metadata>
   <routes>
     <route path="/avatica">
         <rewrite apply="AVATICA/avatica/inbound/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
index 76c39f1..c3a4555 100644
--- a/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
@@ -21,6 +21,12 @@
    This service definition does not cover the web UI.
 -->
 <service role="CM-API" name="cm-api" version="1.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/cm-api</context>
+        <shortDesc>Cloudera Manager REST API</shortDesc>
+        <description>Cloudera Manager's REST API lets you work with existing tools, and programmatically manage your Hadoop clusters. The API is available in both Cloudera Express and Cloudera Enterprise, and comes with open-source client libraries.</description>
+    </metadata>
   <routes>
     <route path="/cm-api/**">
       <rewrite apply="CM-API/cm-api/rest" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/cm-ui/1.0.0/rewrite.xml b/gateway-service-definitions/src/main/resources/services/cm-ui/1.0.0/rewrite.xml
new file mode 100644
index 0000000..a202e8d
--- /dev/null
+++ b/gateway-service-definitions/src/main/resources/services/cm-ui/1.0.0/rewrite.xml
@@ -0,0 +1,33 @@
+<!--
+   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.
+-->
+<rules>
+  <rule dir="IN" name="CM-UI/cm-ui/ui/inbound" pattern="*://*:*/**/cmf/{xxx_unique_path=**}?{**}">
+    <rewrite template="{$serviceUrl[CM-UI]}/cmf/{xxx_unique_path=**}?{**}"/>
+  </rule>
+  <rule dir="IN" name="CM-UI/cm-ui/ui/root" pattern="*://*:*/**/cmf/">
+    <rewrite template="{$serviceUrl[CM-UI]}/cmf/"/>
+  </rule>
+  <rule dir="IN" name="CM-UI/cm-ui/static/inbound" pattern="*://*:*/**/static/{xxx_unique_path=**}?{**}">
+    <rewrite template="{$serviceUrl[CM-UI]}/static/{xxx_unique_path=**}?{**}"/>
+  </rule>
+  <rule dir="IN" name="CM-UI/cm-ui/rest" pattern="*://*:*/**/api/{xxx_unique_path=**}?{**}">
+    <rewrite template="{$serviceUrl[CM-UI]}/api/{xxx_unique_path=**}?{**}"/>
+  </rule>
+  <rule dir="IN" name="CM-UI/cm-ui/root" pattern="*://*:*/*/*/{xxx_unique_path=*}?{**}">
+    <rewrite template="{$serviceUrl[CM-UI]}/{xxx_unique_path=*}?{**}"/>
+  </rule>
+</rules>
diff --git a/gateway-service-definitions/src/main/resources/services/cm-ui/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/cm-ui/1.0.0/service.xml
new file mode 100644
index 0000000..84892b5
--- /dev/null
+++ b/gateway-service-definitions/src/main/resources/services/cm-ui/1.0.0/service.xml
@@ -0,0 +1,62 @@
+<!--
+   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.
+-->
+
+<!--
+   Knox service definition for Cloudera Manager UI
+
+   This service definition requires the use of a default topology or topology
+   port mapping. Paths must be accessed without the "/gateway/<topology>"
+   modifier in the URL.
+-->
+
+<service role="CM-UI" name="cm-ui" version="1.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/cmf</context>
+        <shortDesc>Cloudera Manager Admin Console</shortDesc>
+        <description>Cloudera Manager Admin Console is the web-based UI that you use to configure, manage, and monitor CDH.</description>
+    </metadata>
+    <routes>
+        <route path="/cmf/**">
+            <rewrite apply="CM-UI/cm-ui/ui/inbound" to="request.url"/>
+        </route>
+
+        <!-- The previous route /cmf/** does not match /cmf/  -->
+        <route path="/cmf/">
+        <rewrite apply="CM-UI/cm-ui/ui/root" to="request.url"/>
+        </route>
+        <route path="/static/**">
+            <rewrite apply="CM-UI/cm-ui/static/inbound" to="request.url"/>
+        </route>
+        <route path="/api/**">
+            <rewrite apply="CM-UI/cm-ui/rest" to="request.url"/>
+        </route>
+
+        <!-- For paths that do not start with /cmf, /static or /api -->
+        <route path="/*">
+            <rewrite apply="CM-UI/cm-ui/root" to="request.url"/>
+        </route>
+    </routes>
+    <dispatch classname="org.apache.knox.gateway.dispatch.ConfigurableDispatch"
+              ha-classname="org.apache.knox.gateway.ha.dispatch.ConfigurableHADispatch">
+        <param>
+            <name>responseExcludeHeaders</name>
+            <value>WWW-AUTHENTICATE</value>
+        </param>
+    </dispatch>
+</service>
+
diff --git a/gateway-service-definitions/src/main/resources/services/datanode/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/datanode/1.0.0/service.xml
index 2d898cf..32cac0d 100644
--- a/gateway-service-definitions/src/main/resources/services/datanode/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/datanode/1.0.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="DATANODE" name="datanode" version="1.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/datanode</context>
+        <shortDesc>Datanode</shortDesc>
+        <description>DataNode works as Slave in Hadoop cluster. This actually stores Business data. This is actual worker node were Read/Write/Data processing is handled. Upon instruction from Master, it performs creation/replication/deletion of data blocks.</description>
+    </metadata>
     <routes>
         <route path="/datanode/">
            <rewrite apply="DATANODE/outbound/datanode/static" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml b/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
index 9f1f52f..ab089c0 100644
--- a/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
@@ -15,7 +15,15 @@
    limitations under the License.
 -->
 <service role="DRUID-BROKER" name="druid-broker" version="0.0.1">
-  <routes>
+    <metadata>
+        <type>API</type>
+        <context>/druid-broker/druid</context>
+        <shortDesc>Druid Broker API</shortDesc>
+        <description>The Broker is the process to route queries to if you want to run a distributed cluster. 
+            It understands the metadata published to ZooKeeper about what segments exist on what processes and routes queries such that they hit the right processes. 
+            This process also merges the result sets from all of the individual processes together. On start up, Historical processes announce themselves and the segments they are serving in Zookeeper.</description>
+    </metadata>
+    <routes>
     <route path="druid-broker/druid/broker/v1/{**}?{**}">
         <rewrite apply="DRUID-BROKER/druid-broker/inbound/api"/>
     </route>
diff --git a/gateway-service-definitions/src/main/resources/services/druid-coordinator-ui/0.0.1/service.xml b/gateway-service-definitions/src/main/resources/services/druid-coordinator-ui/0.0.1/service.xml
index 98950da..d8d4838 100644
--- a/gateway-service-definitions/src/main/resources/services/druid-coordinator-ui/0.0.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/druid-coordinator-ui/0.0.1/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="DRUID-COORDINATOR-UI" name="druid-coordinator-ui" version="0.0.1">
+    <metadata>
+        <type>UI</type>
+        <context>/druid-coordinator-ui</context>
+        <shortDesc>Druid Coordinator Console</shortDesc>
+        <description>The Druid Coordinator exposes a web GUI for displaying cluster information and rule configuration.</description>
+    </metadata>
   <routes>
     <route path="druid-coordinator-ui">
       <rewrite apply="DRUID-COORDINATOR-UI/druid-coordinator-ui/inbound/root"/>
diff --git a/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml b/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
index bb92f78..244e50f 100644
--- a/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
@@ -15,7 +15,15 @@
    limitations under the License.
 -->
 <service role="DRUID-COORDINATOR" name="druid-coordinator" version="0.0.1">
-  <routes>
+    <metadata>
+        <type>API</type>
+        <context>/druid-coordinator</context>
+        <shortDesc>Druid Coordinator API</shortDesc>
+        <description>The Druid Coordinator process is primarily responsible for segment management and distribution. 
+            More specifically, the Druid Coordinator process communicates to Historical processes to load or drop segments based on configurations. 
+            The Druid Coordinator is responsible for loading new segments, dropping outdated segments, managing segment replication, and balancing segment load.</description>
+    </metadata>
+    <routes>
     <route path="druid-coordinator/status">
       <rewrite apply="DRUID-COORDINATOR/druid-coordinator/inbound/status"/>
     </route>
diff --git a/gateway-service-definitions/src/main/resources/services/druid-overlord-ui/0.0.1/service.xml b/gateway-service-definitions/src/main/resources/services/druid-overlord-ui/0.0.1/service.xml
index 49627bc..d42e1cd 100644
--- a/gateway-service-definitions/src/main/resources/services/druid-overlord-ui/0.0.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/druid-overlord-ui/0.0.1/service.xml
@@ -15,7 +15,13 @@
    limitations under the License.
 -->
 <service role="DRUID-OVERLORD-UI" name="druid-overlord-ui" version="0.0.1">
-  <routes>
+    <metadata>
+        <type>UI</type>
+        <context>/druid-overlord-ui</context>
+        <shortDesc>Druid Overlord Console</shortDesc>
+        <description>The Overlord provides a UI for managing tasks and workers.</description>
+    </metadata>
+    <routes>
     <route path="druid-overlord-ui">
       <rewrite apply="DRUID-OVERLORD-UI/druid-overlord-ui/inbound/root"/>
       <rewrite apply="DRUID-OVERLORD-UI/druid-overlord-ui/outbound/links" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml b/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
index 01cd45f..4968bc2 100644
--- a/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="DRUID-OVERLORD" name="druid-overlord" version="0.0.1">
+    <metadata>
+        <type>API</type>
+        <context>/druid-overlord</context>
+        <shortDesc>Druid Overlord API</shortDesc>
+        <description>The Overlord process is responsible for accepting tasks, coordinating task distribution, creating locks around tasks, and returning statuses to callers. 
+            Overlord can be configured to run in one of two modes - local or remote (local being default).</description>
+    </metadata>
   <routes>
     <route path="druid-overlord/druid/indexer/v1/{**}?{**}">
         <rewrite apply="DRUID-OVERLORD/druid-overlord/inbound/api"/>
diff --git a/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml b/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
index b1cccee..3245132 100644
--- a/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="DRUID-ROUTER" name="druid-router" version="0.0.1">
+    <metadata>
+        <type>API</type>
+        <context>/druid-router</context>
+        <shortDesc>Druid Router API</shortDesc>
+        <description>The Apache Druid Router process can be used to route queries to different Broker processes. By default, the broker routes queries based on how Rules are set up</description>
+    </metadata>
   <policies>
     <policy role="webappsec"/>
     <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml b/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
index 28896b5..8d3d611 100644
--- a/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="WEBHBASE" name="webhbase" version="0.98.0">
+    <metadata>
+        <type>API</type>
+        <context>/hbase</context>
+        <shortDesc>Web HBase</shortDesc>
+        <description>The HBase REST server exposes endpoints that provide CRUD (create, read, update, delete) operations for each HBase process, as well as tables, regions, and namespaces.</description>
+    </metadata>
     <routes>
         <route path="/hbase/?**">
             <rewrite apply="WEBHBASE/webhbase/headers/outbound" to="response.headers"/>
diff --git a/gateway-service-definitions/src/main/resources/services/hbaseui/1.1.0/service.xml b/gateway-service-definitions/src/main/resources/services/hbaseui/1.1.0/service.xml
index 09e78ea..4873fca 100644
--- a/gateway-service-definitions/src/main/resources/services/hbaseui/1.1.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hbaseui/1.1.0/service.xml
@@ -16,6 +16,14 @@
    limitations under the License.
 -->
 <service role="HBASEUI" name="hbase" version="1.2.4">
+    <metadata>
+        <type>UI</type>
+        <context>/hbase/webui</context>
+        <shortDesc>HBase UI</shortDesc>
+        <description>The HBase Master web UI is a simple but useful tool, to get an overview of the current status of the cluster. 
+            From its page, you can get the version of the running HBase, its basic configuration, including the root HDFS path and ZooKeeper quorum, 
+            load average of the cluster, and a table, region, and region server list.</description>
+    </metadata>
     <routes>
         <route path="/hbase/webui/">
             <rewrite apply="HBASEUI/hbase/inbound/master/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/hbaseui/2.1.0/service.xml b/gateway-service-definitions/src/main/resources/services/hbaseui/2.1.0/service.xml
index 4b0ecfc..b5efb27 100644
--- a/gateway-service-definitions/src/main/resources/services/hbaseui/2.1.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hbaseui/2.1.0/service.xml
@@ -16,6 +16,14 @@
    limitations under the License.
 -->
 <service role="HBASEUI" name="hbaseui" version="2.1.0">
+    <metadata>
+        <type>UI</type>
+        <context>/hbase/webui</context>
+        <shortDesc>HBase UI</shortDesc>
+        <description>The HBase Master web UI is a simple but useful tool, to get an overview of the current status of the cluster. 
+            From its page, you can get the version of the running HBase, its basic configuration, including the root HDFS path and ZooKeeper quorum, 
+            load average of the cluster, and a table, region, and region server list.</description>
+    </metadata>
     <routes>
         <!-- Fixes the stylesheet on the logs servlet -->
         <route path="/hbase/webui/logs/jetty-dir.css">
diff --git a/gateway-service-definitions/src/main/resources/services/hdfsui/2.7.0/service.xml b/gateway-service-definitions/src/main/resources/services/hdfsui/2.7.0/service.xml
index 9d209a1..611d115 100644
--- a/gateway-service-definitions/src/main/resources/services/hdfsui/2.7.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hdfsui/2.7.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="HDFSUI" name="hdfs" version="2.7.0">
+    <metadata>
+        <type>UI</type>
+        <context>/hdfs/?host={{BACKEND_HOST}}</context>
+        <shortDesc>HDFS Namenode UI</shortDesc>
+        <description>The namenode UI or the namenode web interface is used to monitor the status of the namenode.</description>
+    </metadata>
     <routes>
         <route path="/hdfs/">
             <rewrite apply="HDFSUI/hdfs/outbound/namenode/relative" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/hdfsui/3.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/hdfsui/3.0.0/service.xml
index 8a185e2..a82b011 100644
--- a/gateway-service-definitions/src/main/resources/services/hdfsui/3.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hdfsui/3.0.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="HDFSUI" name="hdfs" version="3.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/hdfs</context>
+        <shortDesc>HDFS Namenode UI</shortDesc>
+        <description>The namenode UI or the namenode web interface is used to monitor the status of the namenode.</description>
+    </metadata>
     <routes>
         <route path="/hdfs/">
             <rewrite apply="HDFSUI/hdfs/outbound/namenode/relative" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/hive/0.13.0/service.xml b/gateway-service-definitions/src/main/resources/services/hive/0.13.0/service.xml
index 26875ff..07e206d 100644
--- a/gateway-service-definitions/src/main/resources/services/hive/0.13.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hive/0.13.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="HIVE" name="hive" version="0.13.0">
+    <metadata>
+        <type>API</type>
+        <context>/hive</context>
+        <shortDesc>Hive</shortDesc>
+        <description>The Apache Hive ™ data warehouse software facilitates reading, writing, and managing large datasets residing in distributed storage using SQL. Structure can be projected onto data already in storage. A command line tool and JDBC driver are provided to connect users to Hive.</description>
+    </metadata>
     <routes>
         <route path="/hive"/>
     </routes>
diff --git a/gateway-service-definitions/src/main/resources/services/hue/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/hue/1.0.0/service.xml
index b0285f6..2b7fea7 100644
--- a/gateway-service-definitions/src/main/resources/services/hue/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/hue/1.0.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="HUE" name="hue" version="1.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/hue</context>
+        <shortDesc>Hue UI</shortDesc>
+        <description>Hue UI is a Web interface for analyzing data with Apache Hadoop</description>
+    </metadata>
   <routes>
     <!-- Since we don't have to rewrite URLs for all javascript, we single out these 2 exceptions: 1 for workers & the other for the base URL -->
     <route path="/hue/desktop/workers/{**}?{**}">
diff --git a/gateway-service-definitions/src/main/resources/services/impala/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/impala/1.0.0/service.xml
index 87364c0..314d7b1 100644
--- a/gateway-service-definitions/src/main/resources/services/impala/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/impala/1.0.0/service.xml
@@ -15,6 +15,14 @@
    limitations under the License.
 -->
 <service role="IMPALA" name="impala" version="1.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/impala</context>
+        <shortDesc>Impala</shortDesc>
+        <description>Impala provides fast, interactive SQL queries directly on your Apache Hadoop data stored in HDFS, HBase, or the Amazon Simple Storage Service (S3). 
+            In addition to using the same unified storage platform, Impala also uses the same metadata, SQL syntax (Hive SQL), ODBC driver, and user interface (Impala query UI in Hue) as Apache Hive. 
+            This provides a familiar and unified platform for real-time or batch-oriented queries.</description>
+    </metadata>
     <routes>
         <route path="/impala"/>
     </routes>
diff --git a/gateway-service-definitions/src/main/resources/services/impalaui/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/impalaui/1.0.0/service.xml
index 3fe808a..1a17098 100644
--- a/gateway-service-definitions/src/main/resources/services/impalaui/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/impalaui/1.0.0/service.xml
@@ -16,6 +16,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 -->
 <service role="IMPALAUI" name="impalaui" version="1.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/impalaui</context>
+        <shortDesc>Impala UI</shortDesc>
+        <description>Each of the Impala daemons (impalad, statestored, and catalogd) includes a built-in web server that displays diagnostic and status information.</description>
+    </metadata>
   <routes>
     <route path="/impalaui/">
       <rewrite apply="IMPALAUI/impala/inbound/basepath" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/jobhistoryui/2.7.0/service.xml b/gateway-service-definitions/src/main/resources/services/jobhistoryui/2.7.0/service.xml
index 4594c01..3045196 100644
--- a/gateway-service-definitions/src/main/resources/services/jobhistoryui/2.7.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/jobhistoryui/2.7.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="JOBHISTORYUI" name="jobhistory" version="2.7.0">
+    <metadata>
+        <type>UI</type>
+        <context>/jobhistory</context>
+        <shortDesc>JobHistory Server Web UI</shortDesc>
+        <description>Web User Interface for YARN Jobhistory Server</description>
+    </metadata>
     <routes>
         <route path="/jobhistory/">
             <rewrite apply="JOBHISTORYUI/jobhistory/outbound/jobs" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/kafka/0.10.0/service.xml b/gateway-service-definitions/src/main/resources/services/kafka/0.10.0/service.xml
index 4e910b2..349b62f 100644
--- a/gateway-service-definitions/src/main/resources/services/kafka/0.10.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/kafka/0.10.0/service.xml
@@ -15,6 +15,15 @@
    limitations under the License.
 -->
 <service role="KAFKA" name="kafka" version="0.10.0">
+    <metadata>
+        <type>API</type>
+        <context>/kafka</context>
+        <shortDesc>Apache Kafka API</shortDesc>
+        <description>Apache Kafka is a distributed streaming platform which provides the following three key capabilities: 
+            1.) Publish and subscribe to streams of records, similar to a message queue or enterprise messaging system.
+            2.) Store streams of records in a fault-tolerant durable way.
+            3.) Process streams of records as they occur.</description>
+    </metadata>
   <routes>
     <route path="/kafka/**"/>
   </routes>
diff --git a/gateway-service-definitions/src/main/resources/services/kuduui/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/kuduui/1.0.0/service.xml
index 6d24478..884982c 100644
--- a/gateway-service-definitions/src/main/resources/services/kuduui/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/kuduui/1.0.0/service.xml
@@ -16,6 +16,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 -->
 <service role="KUDUUI" name="kuduui" version="1.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/kuduui</context>
+        <shortDesc>Kudu UI</shortDesc>
+        <description>Kudu is a columnar storage manager developed for the Apache Hadoop platform. Kudu shares the common technical properties of Hadoop ecosystem applications: it runs on commodity hardware, is horizontally scalable, and supports highly available operation.</description>
+    </metadata>
   <!-- We could also list the OUT rules that write response.body, but for some
        reason Knox runs them automatically even if we don't list them.
   -->
diff --git a/gateway-service-definitions/src/main/resources/services/livy/0.4.0/service.xml b/gateway-service-definitions/src/main/resources/services/livy/0.4.0/service.xml
index c04d66f..a1cc470 100644
--- a/gateway-service-definitions/src/main/resources/services/livy/0.4.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/livy/0.4.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="LIVYSERVER" name="livy" version="0.4.0">
+    <metadata>
+        <type>API</type>
+        <context>/livy</context>
+        <shortDesc>Livy Server</shortDesc>
+        <description>Apache Livy is a service that enables easy interaction with a Spark cluster over a REST interface.</description>
+    </metadata>
   <routes>
     <route path="/livy/**?**"/>
     <route path="/livy"/>
diff --git a/gateway-service-definitions/src/main/resources/services/logsearch/0.5.0/service.xml b/gateway-service-definitions/src/main/resources/services/logsearch/0.5.0/service.xml
index 6e27209..4483fed 100644
--- a/gateway-service-definitions/src/main/resources/services/logsearch/0.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/logsearch/0.5.0/service.xml
@@ -16,7 +16,13 @@
   limitations under the License.
 -->
 <service role="LOGSEARCH" name="logsearch" version="0.5.0">
-  
+    <metadata>
+        <type>UI</type>
+        <context>/logsearch</context>
+        <shortDesc>Ambari LogSearch UI</shortDesc>
+        <description>The Ambari Log Search UI is a purpose-built web application used to search HDP component logs. 
+            The UI is focussed on helping operators quickly access and search logs from a single location. Logs can be filtered by log level, time, component, and can be searched by keyword.</description>
+    </metadata>  
   <routes>
 
     <route path="/logsearch">
diff --git a/gateway-service-definitions/src/main/resources/services/nifi-registry/0.5.0/service.xml b/gateway-service-definitions/src/main/resources/services/nifi-registry/0.5.0/service.xml
index 0b1a32b..0ef7dbe 100644
--- a/gateway-service-definitions/src/main/resources/services/nifi-registry/0.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/nifi-registry/0.5.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="NIFI-REGISTRY" name="nifi-registry" version="0.5.0">
+    <metadata>
+        <type>UI</type>
+        <context>/nifi-registry-app</context>
+        <shortDesc>Nifi Registry UI</shortDesc>
+        <description>Registry — a subproject of Apache NiFi — is a complementary application that provides a central location for storage and management of shared resources across one or more instances of NiFi and/or MiNiFi.</description>
+    </metadata>
     <routes>
         <route path="/nifi-registry-app/**">
             <rewrite apply="NIFI-REGISTRY/nifi-registry/inbound/path" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/nifi/1.4.0/service.xml b/gateway-service-definitions/src/main/resources/services/nifi/1.4.0/service.xml
index d600e2d..e55c971 100644
--- a/gateway-service-definitions/src/main/resources/services/nifi/1.4.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/nifi/1.4.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="NIFI" name="nifi" version="1.4.0">
+    <metadata>
+        <type>UI</type>
+        <context>/nifi-app</context>
+        <shortDesc>Nifi UI</shortDesc>
+        <description>Apache NiFi supports powerful and scalable directed graphs of data routing, transformation, and system mediation logic.</description>
+    </metadata>
     <routes>
         <route path="/nifi-app/**">
             <rewrite apply="NIFI/nifi/inbound/path" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/nodemanagerui/2.7.1/service.xml b/gateway-service-definitions/src/main/resources/services/nodemanagerui/2.7.1/service.xml
index 711b48c..62876b8 100644
--- a/gateway-service-definitions/src/main/resources/services/nodemanagerui/2.7.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/nodemanagerui/2.7.1/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="NODEUI" name="nodeui" version="2.7.1">
+    <metadata>
+        <type>UI</type>
+        <context>/node</context>
+        <shortDesc>YARN NodeManager UI</shortDesc>
+        <description>The NodeManager is responsible for launching and managing containers on a node.</description>
+    </metadata>
     <routes>
         <route path="/node/">
             <rewrite apply="NODEUI/node/root" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
index 455746c..e2c2526 100644
--- a/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="OOZIE" name="oozie" version="4.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/oozie</context>
+        <shortDesc>Oozie Web Services API</shortDesc>
+        <description>Oozie is a workflow scheduler system to manage Apache Hadoop jobs. The Oozie Web Services API is a HTTP REST JSON API.</description>
+    </metadata>
     <routes>
         <route path="/oozie/**?**">
             <rewrite apply="OOZIE/oozie/configuration" to="request.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/oozieui/4.2.0/service.xml b/gateway-service-definitions/src/main/resources/services/oozieui/4.2.0/service.xml
index 8dbe8a7..1e912f6 100644
--- a/gateway-service-definitions/src/main/resources/services/oozieui/4.2.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/oozieui/4.2.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="OOZIEUI" name="oozieui" version="4.2.0">
+    <metadata>
+        <type>UI</type>
+        <context>/oozie</context>
+        <shortDesc>Oozie Web Console</shortDesc>
+        <description>Oozie web console is a web-based tool that gives a read-only view about the jobs.</description>
+    </metadata>
     <routes>
         <route path="/oozie?**">
             <rewrite apply="OOZIEUI/oozieui/inbound/request/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/ranger/0.1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/ranger/0.1.0.0/service.xml
index c652b19..8c9effa 100644
--- a/gateway-service-definitions/src/main/resources/services/ranger/0.1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ranger/0.1.0.0/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="RANGER" name="ranger" version="0.1.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/ranger</context>
+        <shortDesc>Ranger Admin REST API</shortDesc>
+        <description>Apache Ranger is a framework to enable, monitor and manage comprehensive data security across the Hadoop platform. 
+            Apache Ranger currently provides a centralized security adminstration, fine grain access control and detailed auditing for user access within Apache Hadoop, Apache Hive, Apache HBase and other Apache components</description>
+    </metadata>
     <routes>
         <route path="/ranger/service/public/**"/>
         <route path="/ranger/service/plugins/**"/>
diff --git a/gateway-service-definitions/src/main/resources/services/ranger/0.5.0/service.xml b/gateway-service-definitions/src/main/resources/services/ranger/0.5.0/service.xml
index 643a1f3..98c0e43 100644
--- a/gateway-service-definitions/src/main/resources/services/ranger/0.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ranger/0.5.0/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="RANGER" name="ranger" version="0.5.0">
+    <metadata>
+        <type>API</type>
+        <context>/ranger</context>
+        <shortDesc>Ranger Admin REST API</shortDesc>
+        <description>Apache Ranger is a framework to enable, monitor and manage comprehensive data security across the Hadoop platform. 
+            Apache Ranger currently provides a centralized security adminstration, fine grain access control and detailed auditing for user access within Apache Hadoop, Apache Hive, Apache HBase and other Apache components</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
index 9970034..c803bc6 100644
--- a/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="RANGER" name="ranger" version="1.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/ranger</context>
+        <shortDesc>Ranger Admin REST API</shortDesc>
+        <description>Apache Ranger is a framework to enable, monitor and manage comprehensive data security across the Hadoop platform. 
+            Apache Ranger currently provides a centralized security adminstration, fine grain access control and detailed auditing for user access within Apache Hadoop, Apache Hive, Apache HBase and other Apache components</description>
+    </metadata>
     <routes>
         <route path="/ranger/service/public/**"/>
         <route path="/ranger/service/plugins/**"/>
diff --git a/gateway-service-definitions/src/main/resources/services/rangerui/0.5.0/service.xml b/gateway-service-definitions/src/main/resources/services/rangerui/0.5.0/service.xml
index b97e56a..e46f4de 100644
--- a/gateway-service-definitions/src/main/resources/services/rangerui/0.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/rangerui/0.5.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="RANGERUI" name="rangerui" version="0.5.0">
+    <metadata>
+        <type>UI</type>
+        <context>/ranger</context>
+        <shortDesc>Ranger Admin Web UI</shortDesc>
+        <description>Apache Ranger is a framework to enable, monitor and manage comprehensive data security across the Hadoop platform. Ranger Admin Web UI is a web-based tool that provides a way to configure Ranger.</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/rangerui/1.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/rangerui/1.0.0/service.xml
index 0e64b86..1a6263f 100644
--- a/gateway-service-definitions/src/main/resources/services/rangerui/1.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/rangerui/1.0.0/service.xml
@@ -15,6 +15,12 @@
    limitations under the License.
 -->
 <service role="RANGERUI" name="rangerui" version="1.0.0">
+    <metadata>
+        <type>UI</type>
+        <context>/ranger</context>
+        <shortDesc>Ranger Admin Web UI</shortDesc>
+        <description>Apache Ranger is a framework to enable, monitor and manage comprehensive data security across the Hadoop platform. Ranger Admin Web UI is a web-based tool that provides a way to configure Ranger.</description>
+    </metadata>
     <routes>
         <route path="/ranger">
             <rewrite apply="RANGERUI/rangerui/inbound/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/solr/5.5.0/service.xml b/gateway-service-definitions/src/main/resources/services/solr/5.5.0/service.xml
index 9dfeff5..9784944 100644
--- a/gateway-service-definitions/src/main/resources/services/solr/5.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/solr/5.5.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="SOLRAPI" name="solr" version="5.5.0">
+    <metadata>
+        <type>API</type>
+        <context>/solr</context>
+        <shortDesc>SOLR</shortDesc>
+        <description>Solr is a popular, blazing-fast, open source enterprise search platform built on Apache Lucene™.</description>
+    </metadata>
     <policies>
         <policy role="webappsec"/>
         <policy role="authentication"/>
diff --git a/gateway-service-definitions/src/main/resources/services/solr/6.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/solr/6.0.0/service.xml
index 2003298..c264c81 100644
--- a/gateway-service-definitions/src/main/resources/services/solr/6.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/solr/6.0.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="SOLR" name="solr" version="6.0.0">
+    <metadata>
+        <type>API</type>
+        <context>/solr</context>
+        <shortDesc>SOLR</shortDesc>
+        <description>Solr is a popular, blazing-fast, open source enterprise search platform built on Apache Lucene™.</description>
+    </metadata>
     <routes>
         <route path="/solr/">
             <rewrite apply="SOLR/solr/inbound/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/sparkhistoryui/1.4.0/service.xml b/gateway-service-definitions/src/main/resources/services/sparkhistoryui/1.4.0/service.xml
index 2468b6c..bf699df 100644
--- a/gateway-service-definitions/src/main/resources/services/sparkhistoryui/1.4.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/sparkhistoryui/1.4.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="SPARKHISTORYUI" name="sparkhistory" version="1.4.0">
+    <metadata>
+        <type>UI</type>
+        <context>/sparkhistory</context>
+        <shortDesc>Spark History Server Web UI</shortDesc>
+        <description>Spark History Server Web UI provides a comprehensive view of: A list of scheduler stages and tasks - A summary of RDD sizes and memory usage - Environmental information - Information about the running executors.</description>
+    </metadata>
     <routes>
         <route path="/sparkhistory/">
             <rewrite apply="SPARKHISTORYUI/sparkhistory/outbound/rqheaders" to="request.headers"/>
diff --git a/gateway-service-definitions/src/main/resources/services/sparkhistoryui/2.3.0/service.xml b/gateway-service-definitions/src/main/resources/services/sparkhistoryui/2.3.0/service.xml
index 0ff40b3..c984f47 100644
--- a/gateway-service-definitions/src/main/resources/services/sparkhistoryui/2.3.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/sparkhistoryui/2.3.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="SPARKHISTORYUI" name="sparkhistory" version="2.3.0">
+    <metadata>
+        <type>UI</type>
+        <context>/sparkhistory</context>
+        <shortDesc>Spark History Server Web UI</shortDesc>
+        <description>Spark History Server Web UI provides a comprehensive view of: A list of scheduler stages and tasks - A summary of RDD sizes and memory usage - Environmental information - Information about the running executors.</description>
+    </metadata>
     <routes>
         <route path="/sparkhistory/">
             <rewrite apply="SPARKHISTORYUI/sparkhistory/outbound/rqheaders" to="request.headers"/>
diff --git a/gateway-service-definitions/src/main/resources/services/sparkthriftui/2.1.0/service.xml b/gateway-service-definitions/src/main/resources/services/sparkthriftui/2.1.0/service.xml
index 3633899..69eec4d 100644
--- a/gateway-service-definitions/src/main/resources/services/sparkthriftui/2.1.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/sparkthriftui/2.1.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="THRIFTSERVERUI" name="thriftserverui" version="2.1.0">
+    <metadata>
+        <type>UI</type>
+        <context>/thrift</context>
+        <shortDesc>Spark Thrift Server UI</shortDesc>
+        <description>Spark Thrift server is a service that allows JDBC and ODBC clients to run Spark SQL queries. The Spark Thrift server is a variant of HiveServer2.</description>
+    </metadata>
     <routes>
         <route path="/thrift/jobs">
             <rewrite apply="THRIFTSERVERUI/thrift/root/filter/OUT" to="response.body"/>
diff --git a/gateway-service-definitions/src/main/resources/services/storm-logviewer/0.9.3/service.xml b/gateway-service-definitions/src/main/resources/services/storm-logviewer/0.9.3/service.xml
index dd13e65..6098cc8 100644
--- a/gateway-service-definitions/src/main/resources/services/storm-logviewer/0.9.3/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/storm-logviewer/0.9.3/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="STORM-LOGVIEWER" name="storm-logviewer" version="0.9.3">
+    <metadata>
+        <type>UI</type>
+        <context>/storm/logviewer</context>
+        <shortDesc>Apache Storm LogViewer</shortDesc>
+        <description>Apache Storm includes a helpful feature for debugging and monitoring topologies: the logviewer daemon. 
+            With the log viewer you can easily access a specific worker's log in a web browser by clicking on a worker's port number right from Apache Storm UI.</description>
+    </metadata>
     <routes>
         <route path="/storm/logviewer/**"/>
     </routes>
diff --git a/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml b/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
index 4da358c..3549e7e 100644
--- a/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
@@ -15,6 +15,13 @@
    limitations under the License.
 -->
 <service role="STORM" name="storm" version="0.9.3">
+    <metadata>
+        <type>API</type>
+        <context>/storm/api</context>
+        <shortDesc>Apache Storm API</shortDesc>
+        <description>Apache Storm is a free and open source distributed realtime computation system. 
+            Apache Storm makes it easy to reliably process unbounded streams of data, doing for realtime processing what Hadoop did for batch processing.</description>
+    </metadata>
     <routes>
         <route path="/storm/api/**"/>
         <route path="/storm/api/v1/topology/*">
diff --git a/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml b/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
index d8c92c6..b5adb31 100644
--- a/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="WEBHCAT" name="webhcat" version="0.13.0">
+    <metadata>
+        <type>API</type>
+        <context>/templeton</context>
+        <shortDesc>WebHCat</shortDesc>
+        <description>WebHCat is the REST API for HCatalog, a table and storage management layer for Hadoop.</description>
+    </metadata>
     <routes>
         <route path="/templeton/v1/?**"/>
         <route path="/templeton/v1/**?**"/>
diff --git a/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml b/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
index 8da7bd0..a6b9e1b 100644
--- a/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="WEBHDFS" name="webhdfs" version="2.4.0">
+    <metadata>
+        <type>API</type>
+        <context>/webhdfs</context>
+        <shortDesc>Web HDFS</shortDesc>
+        <description>An HTTP REST API which supports the complete FileSystem interface for HDFS.</description>
+    </metadata>
     <routes>
         <route path="/webhdfs/v1/?**">
             <rewrite apply="WEBHDFS/webhdfs/inbound/namenode/root" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml b/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
index e7c721d..722abc6 100644
--- a/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="RESOURCEMANAGER" name="resourcemanager" version="2.5.0">
+    <metadata>
+        <type>API</type>
+        <context>/resourcemanager</context>
+        <shortDesc>YARN Resource Manager</shortDesc>
+        <description>The YARN Resource Manager Service (RM) is the central controlling authority for resource management and makes allocation decisions ResourceManager has two main components: Scheduler and ApplicationsManager.</description>
+    </metadata>
     <routes>
         <route path="/resourcemanager/v1/cluster/"/>
         <route path="/resourcemanager/v1/cluster/**?**"/>
diff --git a/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml b/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
index cf2109d..9a8e4ce 100644
--- a/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="YARNUI" name="yarn" version="2.7.0">
+    <metadata>
+        <type>UI</type>
+        <context>/yarn</context>
+        <shortDesc>YARN Resource Manager Web UI</shortDesc>
+        <description>YARN Resource Manager Web interface (v1)</description>
+    </metadata>
     <routes>
         <route path="/yarn/ws/**">
             <rewrite apply="YARNUI/yarn/inbound/ws" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/yarnuiv2/3.0.0/service.xml b/gateway-service-definitions/src/main/resources/services/yarnuiv2/3.0.0/service.xml
index e97d5ee..ae385f7 100644
--- a/gateway-service-definitions/src/main/resources/services/yarnuiv2/3.0.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/yarnuiv2/3.0.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="YARNUIV2" name="yarnuiv2" version="3.0.0">
+     <metadata>
+        <type>UI</type>
+        <context>/yarnuiv2</context>
+        <shortDesc>YARN Resource Manager Web UI V2</shortDesc>
+        <description>YARN Resource Manager Web interface (v2)</description>
+    </metadata>
   <routes>
     <route path="/yarnuiv2">
       <rewrite apply="YARNUIV2/yarnuiv2/inbound/rootAppScript" to="request.url"/>
diff --git a/gateway-service-definitions/src/main/resources/services/zeppelinui/0.6.0/service.xml b/gateway-service-definitions/src/main/resources/services/zeppelinui/0.6.0/service.xml
index c5a5afb..992991d 100644
--- a/gateway-service-definitions/src/main/resources/services/zeppelinui/0.6.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/zeppelinui/0.6.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="ZEPPELINUI" name="zeppelinui" version="0.6.0">
+    <metadata>
+        <type>UI</type>
+        <context>/zeppelin</context>
+        <shortDesc>Zeppelin Web UI</shortDesc>
+        <description>Zeppelin's web user interface allows end-users to explore Zeppelin notebooks.</description>
+    </metadata>
   <policies>
     <policy role="webappsec"/>
     <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.0/service.xml b/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.0/service.xml
index 7dc98df..93ec9f1 100644
--- a/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="ZEPPELINUI" name="zeppelinui" version="0.8.0">
+    <metadata>
+        <type>UI</type>
+        <context>/zeppelin</context>
+        <shortDesc>Zeppelin Web UI</shortDesc>
+        <description>Zeppelin's web user interface allows end-users to explore Zeppelin notebooks.</description>
+    </metadata>
   <policies>
     <policy role="webappsec"/>
     <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.1/service.xml b/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.1/service.xml
index d010d08..8afd53d 100644
--- a/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/zeppelinui/0.8.1/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="ZEPPELINUI" name="zeppelinui" version="0.8.1">
+    <metadata>
+        <type>UI</type>
+        <context>/zeppelin</context>
+        <shortDesc>Zeppelin Web UI</shortDesc>
+        <description>Zeppelin's web user interface allows end-users to explore Zeppelin notebooks.</description>
+    </metadata>
   <routes>
     <!-- Filter -->
     <route path="/zeppelin/scripts/**">
diff --git a/gateway-service-definitions/src/main/resources/services/zeppelinws/0.6.0/service.xml b/gateway-service-definitions/src/main/resources/services/zeppelinws/0.6.0/service.xml
index 76fb6d3..b57b9e7 100644
--- a/gateway-service-definitions/src/main/resources/services/zeppelinws/0.6.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/zeppelinws/0.6.0/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="ZEPPELINWS" name="zeppelinws" version="0.6.0">
+    <metadata>
+        <type>API</type>
+        <context>/zeppelin/ws</context>
+        <shortDesc>Zeppelin WS API</shortDesc>
+        <description>Apache Zeppelin is a web-based notebook that enables data-driven, interactive data analytics and collaborative documents with SQL, Scala and more.</description>
+    </metadata>
   <policies>
     <policy role="webappsec"/>
     <policy role="authentication" name="Anonymous"/>
diff --git a/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml b/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
index b1d30ac..2e42b33 100644
--- a/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
@@ -16,6 +16,12 @@
    limitations under the License.
 -->
 <service role="ZEPPELINWS" name="zeppelinws" version="0.8.1">
+    <metadata>
+        <type>API</type>
+        <context>/zeppelin/ws</context>
+        <shortDesc>Zeppelin WS API</shortDesc>
+        <description>Apache Zeppelin is a web-based notebook that enables data-driven, interactive data analytics and collaborative documents with SQL, Scala and more.</description>
+    </metadata>
   <routes>
     <route path="/zeppelin/ws">
       <rewrite apply="ZEPPELINWS/zeppelin/ws/inbound" to="request.url"/>
diff --git a/gateway-service-metadata/pom.xml b/gateway-service-metadata/pom.xml
new file mode 100644
index 0000000..29638ab
--- /dev/null
+++ b/gateway-service-metadata/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.knox</groupId>
+        <artifactId>gateway</artifactId>
+        <version>1.4.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>gateway-service-metadata</artifactId>
+    <name>gateway-service-metadata</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-i18n</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-service-definitions</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-provider-jersey</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-util-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>eclipselink</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java
new file mode 100644
index 0000000..5438c41
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "generalProxyInfo")
+public class GeneralProxyInformation {
+
+  @XmlElement
+  private String version;
+
+  @XmlElement
+  private String adminUiUrl;
+
+  @XmlElement
+  private String adminApiBookUrl;
+
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public String getAdminUiUrl() {
+    return adminUiUrl;
+  }
+
+  public void setAdminUiUrl(String adminUiUrl) {
+    this.adminUiUrl = adminUiUrl;
+  }
+
+  public String getAdminApiBookUrl() {
+    return adminApiBookUrl;
+  }
+
+  public void setAdminApiBookUrl(String adminApiBookUrl) {
+    this.adminApiBookUrl = adminApiBookUrl;
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformationMarshaller.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformationMarshaller.java
new file mode 100644
index 0000000..f442d6d
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformationMarshaller.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+
+@Provider
+@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+public class GeneralProxyInformationMarshaller implements MessageBodyWriter<GeneralProxyInformation>{
+  private static Marshaller xmlMarshaller;
+  private static Marshaller jsonMarshaller;
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    return GeneralProxyInformation.class == type;
+  }
+
+  @Override
+  public long getSize(GeneralProxyInformation t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    return -1;
+  }
+
+  @Override
+  public void writeTo(GeneralProxyInformation instance, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
+    try {
+      getMarshaller(mediaType).marshal(instance, entityStream);
+    } catch (JAXBException e) {
+      throw new IOException(e);
+    }
+  }
+
+  private Marshaller getMarshaller(MediaType mediaType) throws JAXBException {
+    return MediaType.APPLICATION_JSON_TYPE.getSubtype().equals(mediaType.getSubtype()) ? getJsonMarshaller() : getXmlMarshaller();
+  }
+
+  private synchronized Marshaller getXmlMarshaller() throws JAXBException {
+    if (xmlMarshaller == null) {
+      final Map<String, Object> properties = new HashMap<>(1);
+      properties.put(JAXBContextProperties.MEDIA_TYPE, MediaType.APPLICATION_XML);
+      xmlMarshaller = JAXBContextFactory.createContext(new Class[] { GeneralProxyInformation.class }, properties).createMarshaller();
+      xmlMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+    }
+    return xmlMarshaller;
+  }
+
+  private synchronized Marshaller getJsonMarshaller() throws JAXBException {
+    if (jsonMarshaller == null) {
+      final Map<String, Object> properties = new HashMap<>(1);
+      properties.put(JAXBContextProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
+      jsonMarshaller = JAXBContextFactory.createContext(new Class[] { GeneralProxyInformation.class }, properties).createMarshaller();
+      jsonMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+    }
+    return jsonMarshaller;
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java
new file mode 100644
index 0000000..1bd0870
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.service.definition.Metadata;
+import org.apache.knox.gateway.service.definition.ServiceDefinitionPair;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServerInfoService;
+import org.apache.knox.gateway.services.ServiceType;
+import org.apache.knox.gateway.services.registry.ServiceDefinitionRegistry;
+import org.apache.knox.gateway.services.security.KeystoreService;
+import org.apache.knox.gateway.services.security.KeystoreServiceException;
+import org.apache.knox.gateway.services.topology.TopologyService;
+import org.apache.knox.gateway.topology.Service;
+import org.apache.knox.gateway.topology.Topology;
+import org.apache.knox.gateway.util.X509CertificateUtil;
+
+@Path("/api/v1/metadata")
+public class KnoxMetadataResource {
+  private static final MetadataServiceMessages LOG = MessagesFactory.get(MetadataServiceMessages.class);
+  private static final String SNAPSHOT_VERSION_POSTFIX = "-SNAPSHOT";
+  private static final Set<String> UNREAL_SERVICES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("NAMENODE", "JOBTRACKER")));
+
+  private java.nio.file.Path pemFilePath;
+  private java.nio.file.Path jksFilePath;
+
+  @Context
+  private HttpServletRequest request;
+
+  @GET
+  @Produces({ APPLICATION_JSON, APPLICATION_XML })
+  @Path("info")
+  public GeneralProxyInformation getGeneralProxyInformation() {
+    final GeneralProxyInformation proxyInfo = new GeneralProxyInformation();
+    final GatewayServices gatewayServices = (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+    if (gatewayServices != null) {
+      final ServerInfoService serviceInfoService = gatewayServices.getService(ServiceType.SERVER_INFO_SERVICE);
+      final String versionInfo = serviceInfoService.getBuildVersion() + " (hash=" + serviceInfoService.getBuildHash() + ")";
+      proxyInfo.setVersion(versionInfo);
+      proxyInfo.setAdminApiBookUrl(
+          String.format(Locale.ROOT, "https://knox.apache.org/books/knox-%s/user-guide.html#Admin+API", getAdminApiBookVersion(serviceInfoService.getBuildVersion())));
+      final GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+      proxyInfo.setAdminUiUrl(getBaseGatewayUrl(config) + "/manager/admin-ui/");
+    }
+
+    return proxyInfo;
+  }
+
+  private String getAdminApiBookVersion(String buildVersion) {
+    return buildVersion.replaceAll(SNAPSHOT_VERSION_POSTFIX, "").replaceAll("\\.", "-");
+  }
+
+  @GET
+  @Produces(APPLICATION_OCTET_STREAM)
+  @Path("publicCert")
+  public Response getPublicCertification(@QueryParam("type") @DefaultValue("pem") String certType) {
+    final GatewayServices gatewayServices = (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+    if (gatewayServices != null) {
+      final GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+      final Certificate certificate = getPublicCertificate(gatewayServices, config);
+      if (certificate != null) {
+        if ("pem".equals(certType)) {
+          generateCertificatePem(certificate, config);
+          return generateSuccessFileDownloadResponse(pemFilePath);
+        } else if ("jks".equals(certType)) {
+          generateCertificateJks(certificate, config);
+          return generateSuccessFileDownloadResponse(jksFilePath);
+        } else {
+          return generateFailureFileDownloadResponse(Status.BAD_REQUEST, "Invalid certification type provided!");
+        }
+      }
+    }
+    return generateFailureFileDownloadResponse(Status.SERVICE_UNAVAILABLE, "Could not generate public certificate");
+  }
+
+  private Response generateSuccessFileDownloadResponse(java.nio.file.Path publicCertFilePath) {
+    final ResponseBuilder responseBuilder = Response.ok(publicCertFilePath.toFile());
+    responseBuilder.header("Content-Disposition", "attachment;filename=" + publicCertFilePath.getFileName().toString());
+    return responseBuilder.build();
+  }
+
+  private Response generateFailureFileDownloadResponse(Status status, String errorMessage) {
+    final ResponseBuilder responseBuilder = Response.status(status);
+    responseBuilder.entity(errorMessage);
+    return responseBuilder.build();
+  }
+
+  private Certificate getPublicCertificate(GatewayServices gatewayServices, GatewayConfig config) {
+    try {
+      final KeystoreService keystoreService = gatewayServices.getService(ServiceType.KEYSTORE_SERVICE);
+      return keystoreService.getKeystoreForGateway().getCertificate(config.getIdentityKeyAlias());
+    } catch (KeyStoreException | KeystoreServiceException e) {
+      LOG.failedToFetchPublicCert(e.getMessage(), e);
+      return null;
+    }
+  }
+
+  private void generateCertificatePem(Certificate certificate, GatewayConfig gatewayConfig) {
+    try {
+      if (pemFilePath == null || !pemFilePath.toFile().exists()) {
+        pemFilePath = Paths.get(gatewayConfig.getGatewaySecurityDir(), "gateway-client-trust.pem");
+        X509CertificateUtil.writeCertificateToFile(certificate, pemFilePath.toFile());
+      }
+    } catch (CertificateEncodingException | IOException e) {
+      LOG.failedToGeneratePublicCert("PEM", e.getMessage(), e);
+    }
+  }
+
+  private void generateCertificateJks(Certificate certificate, GatewayConfig gatewayConfig) {
+    try {
+      if (jksFilePath == null || !jksFilePath.toFile().exists()) {
+        jksFilePath = Paths.get(gatewayConfig.getGatewaySecurityDir(), "gateway-client-trust.jks");
+        X509CertificateUtil.writeCertificateToJks(certificate, jksFilePath.toFile());
+      }
+    } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
+      LOG.failedToGeneratePublicCert("JKS", e.getMessage(), e);
+    }
+  }
+
+  private String getBaseGatewayUrl(GatewayConfig config) {
+    return request.getRequestURL().substring(0, request.getRequestURL().length() - request.getRequestURI().length()) + "/" + config.getGatewayPath();
+  }
+
+  @GET
+  @Produces({ APPLICATION_XML, APPLICATION_JSON })
+  @Path("topologies")
+  public TopologyInformationWrapper getTopologies() {
+    return getTopologies(null);
+  }
+
+  @GET
+  @Produces({ APPLICATION_XML, APPLICATION_JSON })
+  @Path("topologies/{name}")
+  public TopologyInformationWrapper getTopology(@PathParam("name") String topologyName) {
+    return getTopologies(topologyName);
+  }
+
+  private TopologyInformationWrapper getTopologies(String topologyName) {
+    final TopologyInformationWrapper topologies = new TopologyInformationWrapper();
+    final GatewayServices gatewayServices = (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+    final GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+    final ServiceDefinitionRegistry serviceDefinitionRegistry = gatewayServices.getService(ServiceType.SERVICE_DEFINITION_REGISTRY);
+    final Set<String> hiddenTopologies = config.getHiddenTopologiesOnHomepage();
+    if (gatewayServices != null) {
+      final TopologyService topologyService = gatewayServices.getService(ServiceType.TOPOLOGY_SERVICE);
+      for (Topology topology : topologyService.getTopologies()) {
+        if (!hiddenTopologies.contains(topology.getName()) && (topologyName == null || topology.getName().equalsIgnoreCase(topologyName))) {
+          List<ServiceModel> apiServices = new ArrayList<>();
+          List<ServiceModel> uiServices = new ArrayList<>();
+          topology.getServices().stream().filter(service -> !UNREAL_SERVICES.contains(service.getRole())).forEach(service -> {
+            service.getUrls().forEach(serviceUrl -> {
+              ServiceModel serviceModel = getServiceModel(request, config.getGatewayPath(), topology.getName(), service, getServiceMetadata(serviceDefinitionRegistry, service));
+              if (ServiceModel.Type.UI == serviceModel.getType()) {
+                uiServices.add(serviceModel);
+              } else {
+                apiServices.add(serviceModel);
+              }
+            });
+          });
+          topologies.addTopology(topology.getName(), apiServices, uiServices);
+        }
+      }
+    }
+    return topologies;
+  }
+
+  private Metadata getServiceMetadata(ServiceDefinitionRegistry serviceDefinitionRegistry, Service service) {
+    final Optional<ServiceDefinitionPair> serviceDefinition = serviceDefinitionRegistry.getServiceDefinitions().stream()
+        .filter(serviceDefinitionPair -> serviceDefinitionPair.getService().getRole().equalsIgnoreCase(service.getRole())).findFirst();
+    return serviceDefinition.isPresent() ? serviceDefinition.get().getService().getMetadata() : null;
+  }
+
+  private ServiceModel getServiceModel(HttpServletRequest request, String gatewayPath, String topologyName, Service service, Metadata serviceMetadata) {
+    final ServiceModel serviceModel = new ServiceModel();
+    serviceModel.setRequest(request);
+    serviceModel.setGatewayPath(gatewayPath);
+    serviceModel.setTopologyName(topologyName);
+    serviceModel.setService(service);
+    serviceModel.setServiceMetadata(serviceMetadata);
+    return serviceModel;
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataServiceDeploymentContributor.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataServiceDeploymentContributor.java
new file mode 100644
index 0000000..3219ac4
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataServiceDeploymentContributor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import org.apache.knox.gateway.jersey.JerseyServiceDeploymentContributorBase;
+
+public class KnoxMetadataServiceDeploymentContributor extends JerseyServiceDeploymentContributorBase {
+
+  @Override
+  public String getRole() {
+    return "KNOX-METADATA";
+  }
+
+  @Override
+  public String getName() {
+    return "knox-metadata";
+  }
+
+  @Override
+  protected String[] getPackages() {
+    return new String[] { "org.apache.knox.gateway.service.metadata" };
+  }
+
+  @Override
+  protected String[] getPatterns() {
+    return new String[] { "*/**?**" };
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/MetadataServiceMessages.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/MetadataServiceMessages.java
new file mode 100644
index 0000000..e8dc952
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/MetadataServiceMessages.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import org.apache.knox.gateway.i18n.messages.Message;
+import org.apache.knox.gateway.i18n.messages.MessageLevel;
+import org.apache.knox.gateway.i18n.messages.Messages;
+import org.apache.knox.gateway.i18n.messages.StackTrace;
+
+@Messages(logger = "org.apache.knox.gateway.service.metadata")
+public interface MetadataServiceMessages {
+
+  @Message(level = MessageLevel.ERROR, text = "Failed to fetch public certificate: {1}")
+  void failedToFetchPublicCert(String errorMessage, @StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+  @Message(level = MessageLevel.ERROR, text = "Failed to generate public certificate {0}: {1}")
+  void failedToGeneratePublicCert(String certificateType, String errorMessage, @StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java
new file mode 100644
index 0000000..e631a7d
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.knox.gateway.service.definition.Metadata;
+import org.apache.knox.gateway.topology.Service;
+
+@XmlRootElement(name = "service")
+@XmlAccessorType(XmlAccessType.NONE)
+public class ServiceModel {
+
+  public enum Type {
+    API, UI, UNKNOWN
+  };
+
+  protected HttpServletRequest request;
+  protected String topologyName;
+  protected String gatewayPath;
+  protected Service service;
+  protected Metadata serviceMetadata;
+
+  public void setRequest(HttpServletRequest request) {
+    this.request = request;
+  }
+
+  public void setTopologyName(String topologyName) {
+    this.topologyName = topologyName;
+  }
+
+  public void setGatewayPath(String gatewayPath) {
+    this.gatewayPath = gatewayPath;
+  }
+
+  public void setService(Service service) {
+    this.service = service;
+  }
+
+  public void setServiceMetadata(Metadata serviceMetadata) {
+    this.serviceMetadata = serviceMetadata;
+  }
+
+  @XmlElement
+  public String getServiceName() {
+    return this.service == null ? "" : service.getRole();
+  }
+
+  @XmlElement
+  public String getVersion() {
+    return this.service == null ? "" : this.service.getVersion() == null ? "" : this.service.getVersion().toString();
+  }
+
+  @XmlElement(name = "shortDesc")
+  public String getShortDescription() {
+    if (serviceMetadata == null) {
+      return getServiceName().substring(0, 1).toUpperCase(Locale.ROOT) + getServiceName().substring(1).toLowerCase(Locale.ROOT);
+    } else {
+      return serviceMetadata.getShortDesc();
+    }
+  }
+
+  @XmlElement
+  public String getDescription() {
+    if (serviceMetadata == null) {
+      return getShortDescription() + (Type.API == getType() ? " REST API" : Type.UI == getType() ? " Web User Interface" : "");
+    } else {
+      return serviceMetadata.getDescription();
+    }
+  }
+
+  @XmlElement
+  public Type getType() {
+    return serviceMetadata == null ? Type.UNKNOWN : Type.valueOf(serviceMetadata.getType());
+  }
+
+  @XmlElement
+  public String getContext() {
+    return (serviceMetadata == null ? "/" + getServiceName().toLowerCase(Locale.ROOT) : serviceMetadata.getContext()) + "/";
+  }
+
+  @XmlElement
+  public String getServiceUrl() {
+    String context = getContext();
+    if ("HIVE".equals(getServiceName())) {
+      return String.format(Locale.ROOT, "jdbc:hive2://%s:%d/;?hive.server2.transport.mode=http;hive.server2.thrift.http.path=/%s/%s%s", request.getServerName(),
+          request.getServerPort(), gatewayPath, topologyName, context);
+    } else {
+      if (context.indexOf("{{BACKEND_HOST}}") > -1) {
+        context = context.replace("{{BACKEND_HOST}}", getBackendServiceUrl());
+      }
+      return String.format(Locale.ROOT, "%s://%s:%s/%s/%s%s", request.getScheme(), request.getServerName(), request.getServerPort(), gatewayPath, topologyName, context);
+    }
+  }
+
+  protected String getBackendServiceUrl() {
+    final String serviceUrl = service == null ? "" : service.getUrl();
+    return serviceUrl == null ? "" : serviceUrl;
+  }
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformation.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformation.java
new file mode 100644
index 0000000..0ede6e7
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformation.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "topology")
+public class TopologyInformation {
+
+  @XmlElement(name = "topology")
+  private String topologyName;
+
+  @XmlElement(name = "service")
+  @XmlElementWrapper(name = "apiServices")
+  private List<ServiceModel> apiServices;
+
+  @XmlElement(name = "service")
+  @XmlElementWrapper(name = "uiServices")
+  private List<ServiceModel> uiServices;
+
+  public String getTopologyName() {
+    return topologyName;
+  }
+
+  public void setTopologyName(String topologyName) {
+    this.topologyName = topologyName;
+  }
+
+  public List<ServiceModel> getApiServices() {
+    return apiServices;
+  }
+
+  public void setApiServices(List<ServiceModel> apiServices) {
+    this.apiServices = apiServices;
+  }
+
+  public List<ServiceModel> getUiServices() {
+    return uiServices;
+  }
+
+  public void setUiServices(List<ServiceModel> uiServices) {
+    this.uiServices = uiServices;
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformationWrapper.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformationWrapper.java
new file mode 100644
index 0000000..6846c34
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformationWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class TopologyInformationWrapper {
+
+  @XmlElement(name = "topologyInformation")
+  @XmlElementWrapper(name = "topologyInformations")
+  private Set<TopologyInformation> topologies = new HashSet<>();
+
+  public Set<TopologyInformation> getTopologies() {
+    return topologies;
+  }
+
+  public void addTopology(String name, List<ServiceModel> apiServices, List<ServiceModel> uiServices) {
+    final TopologyInformation topology = new TopologyInformation();
+    topology.setTopologyName(name);
+    topology.setApiServices(apiServices);
+    topology.setUiServices(uiServices);
+    this.topologies.add(topology);
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformationWrapperMarshaller.java b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformationWrapperMarshaller.java
new file mode 100644
index 0000000..770be12
--- /dev/null
+++ b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/TopologyInformationWrapperMarshaller.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package org.apache.knox.gateway.service.metadata;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+
+@Provider
+@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+public class TopologyInformationWrapperMarshaller implements MessageBodyWriter<TopologyInformationWrapper> {
+  private static Marshaller xmlMarshaller;
+  private static Marshaller jsonMarshaller;
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    return TopologyInformationWrapper.class == type;
+  }
+
+  @Override
+  public long getSize(TopologyInformationWrapper t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    return -1;
+  }
+
+  @Override
+  public void writeTo(TopologyInformationWrapper instance, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+      MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
+    try {
+      getMarshaller(mediaType).marshal(instance, entityStream);
+    } catch (JAXBException e) {
+      throw new IOException(e);
+    }
+  }
+
+  private Marshaller getMarshaller(MediaType mediaType) throws JAXBException {
+    return MediaType.APPLICATION_JSON_TYPE.getSubtype().equals(mediaType.getSubtype()) ? getJsonMarshaller() : getXmlMarshaller();
+  }
+
+  private synchronized Marshaller getXmlMarshaller() throws JAXBException {
+    if (xmlMarshaller == null) {
+      final Map<String, Object> properties = new HashMap<>(1);
+      properties.put(JAXBContextProperties.MEDIA_TYPE, MediaType.APPLICATION_XML);
+      xmlMarshaller = JAXBContextFactory.createContext(new Class[] { TopologyInformationWrapper.class }, properties).createMarshaller();
+      xmlMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+    }
+    return xmlMarshaller;
+  }
+
+  private synchronized Marshaller getJsonMarshaller() throws JAXBException {
+    if (jsonMarshaller == null) {
+      final Map<String, Object> properties = new HashMap<>(1);
+      properties.put(JAXBContextProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
+      jsonMarshaller = JAXBContextFactory.createContext(new Class[] { TopologyInformationWrapper.class }, properties).createMarshaller();
+      jsonMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+    }
+    return jsonMarshaller;
+  }
+
+}
diff --git a/gateway-service-metadata/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ServiceDeploymentContributor b/gateway-service-metadata/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ServiceDeploymentContributor
new file mode 100644
index 0000000..ad2bb99
--- /dev/null
+++ b/gateway-service-metadata/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ServiceDeploymentContributor
@@ -0,0 +1,18 @@
+##########################################################################
+# 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.
+##########################################################################
+org.apache.knox.gateway.service.metadata.KnoxMetadataServiceDeploymentContributor
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java
index 11ffe36..d6e40a0 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java
@@ -670,4 +670,9 @@ public interface GatewayConfig {
    * @return eviction grace period in seconds
    */
   long getKnoxTokenEvictionGracePeriod();
+
+  /**
+   * @return the list of topologies that should be hidden on Knox homepage
+   */
+  Set<String> getHiddenTopologiesOnHomepage();
 }
diff --git a/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java b/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
index 9e15c91..a7774bc 100644
--- a/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
+++ b/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
@@ -789,4 +789,9 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig {
   public long getKnoxTokenEvictionGracePeriod() {
     return 0;
   }
+
+  @Override
+  public Set<String> getHiddenTopologiesOnHomepage() {
+    return Collections.emptySet();
+  }
 }
diff --git a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAppFuncTest.java b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAppFuncTest.java
index 5791b5d..c061479 100644
--- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAppFuncTest.java
+++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAppFuncTest.java
@@ -18,6 +18,7 @@
 package org.apache.knox.gateway;
 
 import java.io.File;
+import java.io.FilenameFilter;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
@@ -26,6 +27,8 @@ import java.util.Properties;
 import java.util.UUID;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.NotFileFilter;
+import org.apache.commons.io.filefilter.PrefixFileFilter;
 import org.apache.knox.gateway.services.DefaultGatewayServices;
 import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.ServiceLifecycleException;
@@ -57,6 +60,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
 public class GatewayAppFuncTest {
   private static final Logger LOG = LoggerFactory.getLogger( GatewayAppFuncTest.class );
   private static final Class<?> DAT = GatewayAppFuncTest.class;
+  private static final FilenameFilter EXCLUDE_HOMEPAGE_DEPLOYMENT_FILE_FILTER = new NotFileFilter(new PrefixFileFilter("homepage"));
 
   private static GatewayTestConfig config;
   private static DefaultGatewayServices services;
@@ -298,7 +302,7 @@ public class GatewayAppFuncTest {
         .get( clusterUrl + "/dynamic-app" );
 
     File deployDir = new File( config.getGatewayDeploymentDir() );
-    assertThat( deployDir.listFiles(), is(arrayWithSize(0)) );
+    assertThat( deployDir.listFiles(EXCLUDE_HOMEPAGE_DEPLOYMENT_FILE_FILTER), is(arrayWithSize(0)) );
 
     LOG_EXIT();
   }
@@ -456,7 +460,7 @@ public class GatewayAppFuncTest {
         .when().get( clusterUrl + "/test.xml" );
 
     File deployDir = new File( config.getGatewayDeploymentDir() );
-    assertThat( deployDir.listFiles(), is(arrayWithSize(0)) );
+    assertThat( deployDir.listFiles(EXCLUDE_HOMEPAGE_DEPLOYMENT_FILE_FILTER), is(arrayWithSize(0)) );
 
     LOG_EXIT();
   }
@@ -481,7 +485,7 @@ public class GatewayAppFuncTest {
       topos.reloadTopologies();
 
       File deployDir = new File( config.getGatewayDeploymentDir() );
-      String[] topoDirs1 = deployDir.list();
+      String[] topoDirs1 = deployDir.list(EXCLUDE_HOMEPAGE_DEPLOYMENT_FILE_FILTER);
       assertThat( topoDirs1, is(arrayWithSize(1)) );
 
       given()
@@ -497,7 +501,7 @@ public class GatewayAppFuncTest {
       FileUtils.touch( topoFile );
 
       topos.reloadTopologies();
-      String[] topoDirs2 = deployDir.list();
+      String[] topoDirs2 = deployDir.list(EXCLUDE_HOMEPAGE_DEPLOYMENT_FILE_FILTER);
       assertThat( topoDirs2, is(arrayWithSize(2)) );
       assertThat( topoDirs2, hasItemInArray(topoDirs1[0]) );
 
@@ -514,7 +518,7 @@ public class GatewayAppFuncTest {
       FileUtils.touch( topoFile );
       topos.reloadTopologies();
 
-      String[] topoDirs3 = deployDir.list();
+      String[] topoDirs3 = deployDir.list(EXCLUDE_HOMEPAGE_DEPLOYMENT_FILE_FILTER);
       assertThat( topoDirs3, is(arrayWithSize(2)) );
       assertThat( topoDirs3, not(hasItemInArray(topoDirs1[0])) );
 
@@ -553,7 +557,7 @@ public class GatewayAppFuncTest {
 
       File deployDir = new File( config.getGatewayDeploymentDir() );
       String[] topoDirs = deployDir.list();
-      assertThat( topoDirs, is(arrayWithSize(1)) );
+      assertThat( topoDirs, is(arrayWithSize(2)) );
 
       String username = "guest";
       String password = "guest-password";
diff --git a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java
index 339295e..6506670 100644
--- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java
+++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java
@@ -173,7 +173,7 @@ public class GatewayDeployFuncTest {
 
     // Make sure deployment directory is empty.
     assertThat( topoDir.listFiles().length, is( 0 ) );
-    assertThat( deployDir.listFiles().length, is( 0 ) );
+    assertThat( deployDir.listFiles().length, is( 1 ) );
 
     File descriptor = writeTestTopology( "test-cluster", createTopology() );
     long writeTime = System.currentTimeMillis();
@@ -224,7 +224,7 @@ public class GatewayDeployFuncTest {
     // Wait to make sure a second has passed to ensure the the file timestamps are different.
     waitForElapsed( writeTime, 1000, 100 );
 
-    waitForFiles( deployDir, ".*", 0, -1, sleep );
+    waitForFiles( deployDir, ".*", 1, -1, sleep );
 
     // Wait a bit more to make sure undeployment finished.
     Thread.sleep( sleep );
@@ -236,7 +236,7 @@ public class GatewayDeployFuncTest {
 
     // Make sure deployment directory is empty.
     assertThat( topoDir.listFiles().length, is( 0 ) );
-    assertThat( deployDir.listFiles().length, is( 0 ) );
+    assertThat( deployDir.listFiles().length, is( 1 ) );
     LOG_EXIT();
   }
 
diff --git a/knox-homepage-ui/.gitignore b/knox-homepage-ui/.gitignore
new file mode 100644
index 0000000..6f66bd2
--- /dev/null
+++ b/knox-homepage-ui/.gitignore
@@ -0,0 +1,12 @@
+
+# ui dependencies
+node_modules
+bower_components
+
+# ui misc
+.sass-cache
+connect.lock
+coverage/*
+libpeerconnection.log
+npm-debug.log
+testem.log
diff --git a/knox-homepage-ui/angular-cli.json b/knox-homepage-ui/angular-cli.json
new file mode 100644
index 0000000..6ec75ac
--- /dev/null
+++ b/knox-homepage-ui/angular-cli.json
@@ -0,0 +1,54 @@
+{
+  "project": {
+    "version": "1.0.0",
+    "name": "ng-knox-homepage"
+  },
+  "apps": [
+    {
+      "root": "homepage",
+      "outDir": "target/classes/homepage/app",
+      "assets": [
+        "assets",
+        "favicon.ico"
+      ],
+      "index": "index.html",
+      "main": "main.ts",
+      "test": "test.ts",
+      "tsconfig": "tsconfig.json",
+      "prefix": "app",
+      "mobile": false,
+      "styles": [
+        "../node_modules/bootstrap/dist/css/bootstrap.min.css",
+        "styles.css"
+      ],
+      "scripts": [
+        "../node_modules/jquery/dist/jquery.min.js",
+        "../node_modules/bootstrap/dist/js/bootstrap.js"
+      ],
+      "environmentSource": "environments/environment.ts",
+      "environments": {
+        "dev": "environments/environment.ts",
+        "prod": "environments/environment.prod.ts"
+      }
+    }
+  ],
+  "addons": [],
+  "packages": [],
+  "e2e": {
+    "protractor": {
+      "config": "./protractor.conf.js"
+    }
+  },
+  "test": {
+    "karma": {
+      "config": "./karma.conf.js"
+    }
+  },
+  "defaults": {
+    "styleExt": "css",
+    "component": {
+      "inlineTemplate": false,
+      "spec": true
+    }
+  }
+}
diff --git a/knox-homepage-ui/homepage/app/app.module.ts b/knox-homepage-ui/homepage/app/app.module.ts
new file mode 100644
index 0000000..f8f3186
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/app.module.ts
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+import {NgModule} from '@angular/core';
+import {DataTableModule} from 'angular2-datatable';
+import {BrowserModule} from '@angular/platform-browser';
+import {HttpClientModule, HttpClientXsrfModule} from '@angular/common/http';
+
+import {GeneralProxyInformationComponent} from './generalProxyInformation/general.proxy.information.component';
+import {TopologyInformationsComponent} from './topologies/topology.information.component';
+import {HomepageService} from './homepage.service';
+
+@NgModule({
+    imports: [BrowserModule,
+        HttpClientModule,
+        HttpClientXsrfModule,
+        DataTableModule
+    ],
+    declarations: [GeneralProxyInformationComponent,
+                   TopologyInformationsComponent
+    ],
+    providers: [HomepageService
+    ],
+    bootstrap: [GeneralProxyInformationComponent,
+                TopologyInformationsComponent
+    ]
+})
+export class AppModule {
+}
diff --git a/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.component.html b/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.component.html
new file mode 100644
index 0000000..4c32b03
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.component.html
@@ -0,0 +1,57 @@
+<!--
+  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.
+-->
+<h4>General Proxy Information</h4>
+<div class="table-responsive">
+    <table class="table table-striped table-hover">
+        <tbody>
+            <tr>
+                <td>Knox Version</td>
+                <td>{{ getVersion() }}</td>
+            </tr>
+            <tr>
+                <td>TLS Public Certificate</td>
+                <td>
+                    <a href="{{ getMetadataAPIUrl('publicCert?type=pem') }}">PEM</a>
+                    &nbsp;&nbsp;|&nbsp;&nbsp;
+                    <a href="{{ getMetadataAPIUrl('publicCert?type=jks') }}">JKS</a>
+                </td>
+            </tr>
+            <tr>
+                <td>Admin UI URL</td>
+                <td><a href="{{ getAdminUiUrl() }}" target="_blank">{{ getAdminUiUrl() }}</a></td>
+            </tr>
+            <tr>
+                <td>
+                    Admin API Details
+                    <span class="inline-glyph glyphicon glyphicon-info-sign btn btn-xs"
+                    title="{{ getAdminApiDescription() }}" data-toggle="tooltip"></span>
+                </td>
+                <td>
+                    <a href="{{ getAdminApiBookUrl() }}" target="_blank">{{ getAdminApiBookUrl() }}</a>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    Metadata API
+                </td>
+                <td>
+                    <a href="{{ getMetadataAPIUrl('info') }}" target="_blank">General Proxy Information</a>
+                    &nbsp;&nbsp;|&nbsp;&nbsp;
+                    <a href="{{ getMetadataAPIUrl('topologies') }}" target="_blank">Topologies</a>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
\ No newline at end of file
diff --git a/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.component.ts b/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.component.ts
new file mode 100644
index 0000000..7ba4abd
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.component.ts
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+import {Component, OnInit} from '@angular/core';
+import {HomepageService} from '../homepage.service';
+import {GeneralProxyInformation} from './general.proxy.information';
+
+@Component({
+    selector: 'app-general-proxy-information',
+    templateUrl: './general.proxy.information.component.html',
+    providers: [HomepageService]
+})
+
+export class GeneralProxyInformationComponent implements OnInit {
+
+    generalProxyInformation: GeneralProxyInformation;
+
+    constructor(private homepageService: HomepageService) {}
+
+    getVersion() {
+        if (this.generalProxyInformation) {
+            return this.generalProxyInformation.version;
+          }
+          return '';
+    }
+
+    getAdminUiUrl() {
+        if (this.generalProxyInformation) {
+            return this.generalProxyInformation.adminUiUrl;
+          }
+        return '';
+    }
+
+    getMetadataAPIUrl(endpoint: string) {
+        return this.getAdminUiUrl().replace('manager/admin-ui/', 'metadata/api/v1/metadata/' + endpoint);
+    }
+
+    getAdminApiDescription() {
+       return 'Knox provides a REST API which allows end-users executing CRUD operations on topologies/shared-porviders/descriptors/'
+              + 'service definitions as well as fetching the Knox version.';
+    }
+
+    getAdminApiBookUrl() {
+        if (this.generalProxyInformation) {
+            return this.generalProxyInformation.adminApiBookUrl;
+          }
+        return '';
+    }
+
+    ngOnInit(): void {
+        console.debug('GeneralProxyInformationComponent --> ngOnInit() --> ');
+        this.homepageService.getGeneralProxyInformation()
+                            .then(generalProxyInformation => this.generalProxyInformation = generalProxyInformation);
+    }
+
+}
diff --git a/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.ts b/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.ts
new file mode 100644
index 0000000..7940c0c
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/generalProxyInformation/general.proxy.information.ts
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+export class GeneralProxyInformation {
+    version: string;
+    adminUiUrl: string;
+    adminApiBookUrl: string;
+}
diff --git a/knox-homepage-ui/homepage/app/homepage.service.ts b/knox-homepage-ui/homepage/app/homepage.service.ts
new file mode 100644
index 0000000..7c3d6a9
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/homepage.service.ts
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+import {Injectable} from '@angular/core';
+import {HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http';
+import swal from 'sweetalert';
+
+import 'rxjs/add/operator/toPromise';
+
+import {GeneralProxyInformation} from './generalProxyInformation/general.proxy.information';
+import {TopologyInformation} from './topologies/topology.information';
+
+@Injectable()
+export class HomepageService {
+    apiUrl = window.location.pathname.replace('home', 'homepage');
+    generalProxyInformationUrl = this.apiUrl + 'homepage/api/v1/metadata/info';
+    publicCertUrl = this.apiUrl + 'homepage/api/v1/metadata/publicCert?type=';
+    topologiesUrl = this.apiUrl + 'homepage/api/v1/metadata/topologies';
+
+    constructor(private http: HttpClient) {}
+
+    getGeneralProxyInformation(): Promise<GeneralProxyInformation> {
+        let headers = new HttpHeaders();
+        headers = this.addJsonHeaders(headers);
+        return this.http.get(this.generalProxyInformationUrl, { headers: headers})
+            .toPromise()
+            .then(response => response['generalProxyInfo'] as GeneralProxyInformation)
+            .catch((err: HttpErrorResponse) => {
+                console.debug('HomepageService --> getGeneralProxyInformation() --> '
+                               + this.generalProxyInformationUrl + '\n  error: ' + err.message);
+                if (err.status === 401) {
+                    window.location.assign(document.location.pathname);
+                } else {
+                    return this.handleError(err);
+                }
+            });
+    }
+
+    getTopologies(): Promise<TopologyInformation[]> {
+        let headers = new HttpHeaders();
+        headers = this.addJsonHeaders(headers);
+        return this.http.get(this.topologiesUrl, { headers: headers})
+            .toPromise()
+            .then(response => response['topologyInformations'].topologyInformation as TopologyInformation[])
+            .catch((err: HttpErrorResponse) => {
+                console.debug('HomepageService --> getTopologies() --> ' + this.topologiesUrl + '\n  error: ' + err.message);
+                if (err.status === 401) {
+                    window.location.assign(document.location.pathname);
+                } else {
+                    return this.handleError(err);
+                }
+            });
+    }
+
+    addJsonHeaders(headers: HttpHeaders): HttpHeaders {
+        return this.addCsrfHeaders(headers.append('Accept', 'application/json').append('Content-Type', 'application/json'));
+    }
+
+    addCsrfHeaders(headers: HttpHeaders): HttpHeaders {
+        return this.addXHRHeaders(headers.append('X-XSRF-Header', 'homepage'));
+    }
+
+    addXHRHeaders(headers: HttpHeaders): HttpHeaders {
+        return headers.append('X-Requested-With', 'XMLHttpRequest');
+    }
+
+    private handleError(error: HttpErrorResponse): Promise<any> {
+        swal('Oops!', 'Something went wrong!\n' + (error.error ? error.error : error.statusText), 'error');
+        return Promise.reject(error.message || error);
+    }
+
+}
diff --git a/knox-homepage-ui/homepage/app/topologies/service.ts b/knox-homepage-ui/homepage/app/topologies/service.ts
new file mode 100644
index 0000000..c3ae63d
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/topologies/service.ts
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+export class Service {
+    description: string;
+    serviceName: string;
+    version: string;
+    serviceUrl: string;
+    shortDesc: string;
+    type: string;
+    context: string;
+}
diff --git a/knox-homepage-ui/homepage/app/topologies/topology.information.component.html b/knox-homepage-ui/homepage/app/topologies/topology.information.component.html
new file mode 100644
index 0000000..3b31775
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/topologies/topology.information.component.html
@@ -0,0 +1,84 @@
+<!--
+  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.
+-->
+<hr/>
+<h4>Topologies</h4>
+<ng-container *ngFor="let topology of topologies">
+    <div>
+      <span [class]="'clickable inline-glyph
+      glyhpicon glyphicon-' + (this['showTopology_' + topology.topology] ? 'minus' : 'plus')"
+      (click)="toggleBoolean('showTopology_' + topology.topology)"></span>
+      <span (click)="toggleBoolean('showTopology_' + topology.topology)"><strong>{{topology.topology}}</strong></span>
+    </div>
+
+    <div class="table-responsive" *ngIf="this['showTopology_' + topology.topology]">
+
+        <!-- UI services -->
+        <table class="table table-hover" [mfData]="topology.uiServices.service" #ui="mfDataTable" [mfRowsOnPage]="5">
+            <thead>
+                <tr *ngIf="topology.uiServices.service.length == 0"><th colspan="2">No UI services found</th></tr>
+                <tr *ngIf="topology.uiServices.service.length > 0"><th colspan="2">UI services</th></tr>
+            </thead>
+            <tbody>
+                <tr *ngFor="let service of ui.data">
+                    <td>
+                        <span class="inline-glyph glyphicon glyphicon-info-sign btn btn-xs"
+                        title="{{service.description}}"
+                        data-toggle="tooltip"></span>
+                        {{service.shortDesc}} <span class="small" *ngIf="service.version">(v{{service.version}})</span>
+                    </td>
+                    <td>
+                        <a href="{{service.serviceUrl}}">{{service.serviceUrl}}</a>
+                    </td>
+                </tr>
+            </tbody>
+      <tfoot>
+          <tr>
+              <td colspan="4">
+                  <mfBootstrapPaginator [rowsOnPageSet]="[5,10,15]"></mfBootstrapPaginator>
+              </td>
+          </tr>
+      </tfoot>
+        </table>
+
+        <!-- API services -->
+        <table class="table table-hover" [mfData]="topology.apiServices.service" #api="mfDataTable" [mfRowsOnPage]="5">
+            <thead>
+                <tr *ngIf="topology.apiServices.service.length == 0"><th colspan="2">No API services found</th></tr>
+                <tr *ngIf="topology.apiServices.service.length > 0"><th colspan="2">API services</th></tr>
+            </thead>
+            <tbody>
+                <tr *ngFor="let service of api.data">
+                    <td>
+                        <span class="inline-glyph glyphicon glyphicon-info-sign btn btn-xs"
+                        title="{{service.description}}"
+                        data-toggle="tooltip"></span>
+                        {{service.shortDesc}} <span class="small" *ngIf="service.version">(v{{service.version}})</span>
+                    </td>
+                    <td>
+                        <a href="{{service.serviceUrl}}">{{service.serviceUrl}}</a>
+                    </td>
+                </tr>
+            </tbody>
+      <tfoot>
+          <tr>
+              <td colspan="4">
+                  <mfBootstrapPaginator [rowsOnPageSet]="[5,10,15]"></mfBootstrapPaginator>
+              </td>
+          </tr>
+      </tfoot>
+        </table>
+    </div>
+</ng-container>
+<hr />
\ No newline at end of file
diff --git a/knox-homepage-ui/homepage/app/topologies/topology.information.component.ts b/knox-homepage-ui/homepage/app/topologies/topology.information.component.ts
new file mode 100644
index 0000000..8f0ff12
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/topologies/topology.information.component.ts
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+import {Component, OnInit} from '@angular/core';
+import {HomepageService} from '../homepage.service';
+import {TopologyInformation} from './topology.information';
+import {Service} from './service';
+
+@Component({
+    selector: 'app-topologies-information',
+    templateUrl: './topology.information.component.html',
+    providers: [HomepageService]
+})
+
+export class TopologyInformationsComponent implements OnInit {
+
+    topologies: TopologyInformation[];
+
+    setTopologies(topologies: TopologyInformation[]) {
+        this.topologies = topologies;
+        for (let topology of topologies) {
+            this['showTopology_' + topology.topology] = false;
+        }
+    }
+
+    toggleBoolean(propertyName: string) {
+        this[propertyName] = !this[propertyName];
+    }
+
+    constructor(private homepageService: HomepageService) {}
+
+    ngOnInit(): void {
+        console.debug('TopologyInformationsComponent --> ngOnInit()');
+        this.homepageService.getTopologies().then(topologies => this.setTopologies(topologies));
+    }
+
+}
diff --git a/knox-homepage-ui/homepage/app/topologies/topology.information.ts b/knox-homepage-ui/homepage/app/topologies/topology.information.ts
new file mode 100644
index 0000000..09d272a
--- /dev/null
+++ b/knox-homepage-ui/homepage/app/topologies/topology.information.ts
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+import {Service} from './service';
+
+export class TopologyInformation {
+    topology: string;
+    apiServices: Service[];
+    uiServices: Service[];
+}
diff --git a/knox-homepage-ui/homepage/assets/.gitkeep b/knox-homepage-ui/homepage/assets/.gitkeep
new file mode 100644
index 0000000..89e5903
--- /dev/null
+++ b/knox-homepage-ui/homepage/assets/.gitkeep
@@ -0,0 +1,17 @@
+##########################################################################
+# 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.
+##########################################################################
diff --git a/knox-homepage-ui/homepage/assets/knox-logo-transparent.gif b/knox-homepage-ui/homepage/assets/knox-logo-transparent.gif
new file mode 100644
index 0000000..7099659
Binary files /dev/null and b/knox-homepage-ui/homepage/assets/knox-logo-transparent.gif differ
diff --git a/knox-homepage-ui/homepage/assets/sticky-footer.css b/knox-homepage-ui/homepage/assets/sticky-footer.css
new file mode 100644
index 0000000..59b129b
--- /dev/null
+++ b/knox-homepage-ui/homepage/assets/sticky-footer.css
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    background-color: #f5f5f5;
+}
+
+.jumbotron {
+    padding: 0.5em 0.6em;
+}
diff --git a/knox-homepage-ui/homepage/environments/environment.prod.ts b/knox-homepage-ui/homepage/environments/environment.prod.ts
new file mode 100644
index 0000000..1627803
--- /dev/null
+++ b/knox-homepage-ui/homepage/environments/environment.prod.ts
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+export const environment = {
+    production: true
+};
diff --git a/knox-homepage-ui/homepage/environments/environment.ts b/knox-homepage-ui/homepage/environments/environment.ts
new file mode 100644
index 0000000..0e41cb3
--- /dev/null
+++ b/knox-homepage-ui/homepage/environments/environment.ts
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+// The file contents for the current environment will overwrite these during build.
+// The build system defaults to the dev environment which uses `environment.ts`, but if you do
+// `ng build --env=prod` then `environment.prod.ts` will be used instead.
+// The list of which env maps to which file can be found in `angular-cli.json`.
+
+export const environment = {
+    production: false
+};
diff --git a/knox-homepage-ui/homepage/favicon.ico b/knox-homepage-ui/homepage/favicon.ico
new file mode 100644
index 0000000..6b1c4a5
Binary files /dev/null and b/knox-homepage-ui/homepage/favicon.ico differ
diff --git a/knox-homepage-ui/homepage/index.html b/knox-homepage-ui/homepage/index.html
new file mode 100644
index 0000000..0feb61c
--- /dev/null
+++ b/knox-homepage-ui/homepage/index.html
@@ -0,0 +1,51 @@
+<!--
+  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.
+-->
+<!doctype html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Apache Knox Home</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="icon" type="image/x-icon" href="favicon.ico">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <!-- Custom styles for this template -->
+    <link href="assets/sticky-footer.css" rel="stylesheet">
+</head>
+<body>
+<div class="navbar-wrapper">
+    <div class="container-fluid">
+        <nav class="navbar navbar-inverse navbar-static-top">
+            <div class="container-fluid">
+                <div class="navbar-header">
+                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
+                            data-target="#navbar" aria-expanded="false" aria-controls="navbar">
+                        <span class="sr-only">Toggle navigation</span>
+                        <span class="icon-bar"></span>
+                        <span class="icon-bar"></span>
+                        <span class="icon-bar"></span>
+                    </button>
+                    <a class="navbar-brand" href="#"> <img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Home"></a>
+                </div>
+            </div>
+        </nav>
+    </div>
+
+    <div class="container-fluid">
+        <app-general-proxy-information></app-general-proxy-information>
+        <app-topologies-information></app-topologies-information>
+    </div>
+</div>
+</body>
+</html>
diff --git a/knox-homepage-ui/homepage/main.ts b/knox-homepage-ui/homepage/main.ts
new file mode 100644
index 0000000..be5f383
--- /dev/null
+++ b/knox-homepage-ui/homepage/main.ts
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+import './polyfills.ts';
+
+import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
+import {enableProdMode} from '@angular/core';
+import {environment} from './environments/environment';
+import {AppModule} from './app/app.module';
+
+if (environment.production) {
+    enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/knox-homepage-ui/homepage/polyfills.ts b/knox-homepage-ui/homepage/polyfills.ts
new file mode 100644
index 0000000..78cba47
--- /dev/null
+++ b/knox-homepage-ui/homepage/polyfills.ts
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+// This file includes polyfills needed by Angular 2 and is loaded before
+// the app. You can add your own extra polyfills to this file.
+import 'core-js/es6/symbol';
+import 'core-js/es6/object';
+import 'core-js/es6/function';
+import 'core-js/es6/parse-int';
+import 'core-js/es6/parse-float';
+import 'core-js/es6/number';
+import 'core-js/es6/math';
+import 'core-js/es6/string';
+import 'core-js/es6/date';
+import 'core-js/es6/array';
+import 'core-js/es6/regexp';
+import 'core-js/es6/map';
+import 'core-js/es6/set';
+import 'core-js/es6/reflect';
+
+import 'core-js/es7/reflect';
+import 'zone.js/dist/zone';
diff --git a/knox-homepage-ui/homepage/styles.css b/knox-homepage-ui/homepage/styles.css
new file mode 100644
index 0000000..56888df
--- /dev/null
+++ b/knox-homepage-ui/homepage/styles.css
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+/* You can add global styles to this file, and also import other style files */
+
+.navbar-static-top {
+    min-height: 110px;
+}
+
+.clickable {
+    cursor: pointer;
+}
diff --git a/knox-homepage-ui/homepage/tsconfig.json b/knox-homepage-ui/homepage/tsconfig.json
new file mode 100644
index 0000000..f04e8cc
--- /dev/null
+++ b/knox-homepage-ui/homepage/tsconfig.json
@@ -0,0 +1,21 @@
+{
+  "compilerOptions": {
+    "baseUrl": "homepage",
+    "declaration": false,
+    "emitDecoratorMetadata": true,
+    "experimentalDecorators": true,
+    "lib": [
+      "es2017",
+      "dom"
+    ],
+    "mapRoot": "./",
+    "module": "es6",
+    "moduleResolution": "node",
+    "outDir": "../dist/out-tsc",
+    "sourceMap": true,
+    "target": "es5",
+    "typeRoots": [
+      "../node_modules/@types"
+    ]
+  }
+}
diff --git a/knox-homepage-ui/npm b/knox-homepage-ui/npm
new file mode 100755
index 0000000..f422a80
--- /dev/null
+++ b/knox-homepage-ui/npm
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+PATH="$DIR/target/node/":$PATH
+node "$DIR/target/node/node_modules/npm/bin/npm-cli.js" --prefix "$DIR" "$@"
diff --git a/gateway-admin-ui/package-lock.json b/knox-homepage-ui/package-lock.json
similarity index 98%
copy from gateway-admin-ui/package-lock.json
copy to knox-homepage-ui/package-lock.json
index 7695dce..ea246f4 100644
--- a/gateway-admin-ui/package-lock.json
+++ b/knox-homepage-ui/package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "ng-knox-ui",
+  "name": "ng-knox-homepage",
   "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
@@ -266,9 +266,9 @@
       "dev": true
     },
     "@types/jasminewd2": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz",
-      "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==",
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.8.tgz",
+      "integrity": "sha512-d9p31r7Nxk0ZH0U39PTH0hiDlJ+qNVGjlt1ucOoTUptxb2v+Y5VMnsxfwN+i3hK4yQnqBi3FMmoMFcd1JHDxdg==",
       "dev": true,
       "requires": {
         "@types/jasmine": "*"
@@ -296,11 +296,6 @@
         "negotiator": "0.6.1"
       }
     },
-    "ace-builds": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.4.2.tgz",
-      "integrity": "sha512-M1JtZctO2Zg+1qeGUFZXtYKsyaRptqQtqpVzlj80I0NzGW9MF3um0DBuizIvQlrPYUlTdm+wcOPZpZoerkxQdA=="
-    },
     "acorn": {
       "version": "5.7.3",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
@@ -711,6 +706,7 @@
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
       "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "dev": true,
       "requires": {
         "core-js": "^2.4.0",
         "regenerator-runtime": "^0.11.0"
@@ -893,7 +889,8 @@
     "bluebird": {
       "version": "3.5.3",
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
-      "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
+      "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
+      "dev": true
     },
     "bn.js": {
       "version": "4.11.8",
@@ -961,14 +958,6 @@
       "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz",
       "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA=="
     },
-    "brace": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/brace/-/brace-0.10.0.tgz",
-      "integrity": "sha1-7e9OubCSi6HuX3F//BV3SabdXXY=",
-      "requires": {
-        "w3c-blob": "0.0.1"
-      }
-    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1627,9 +1616,9 @@
       }
     },
     "core-js": {
-      "version": "2.6.4",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.4.tgz",
-      "integrity": "sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A=="
+      "version": "2.6.11",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+      "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
     },
     "core-object": {
       "version": "3.1.5",
@@ -4617,17 +4606,6 @@
         "pify": "^3.0.0"
       }
     },
-    "libphonenumber-js": {
-      "version": "0.4.52",
-      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-0.4.52.tgz",
-      "integrity": "sha512-Ns5FcEp8W/lZd+lKu7OB46RYBKcncN/S3C51OFh7qXbu6kOFAd75A4M0jtasK3MUWMxKsKXII4WL+GbqaLa2DQ==",
-      "requires": {
-        "babel-runtime": "^6.6.1",
-        "bluebird": "^3.4.6",
-        "minimist": "^1.2.0",
-        "xml2js": "^0.4.17"
-      }
-    },
     "license-webpack-plugin": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.5.0.tgz",
@@ -4948,7 +4926,8 @@
     "minimist": {
       "version": "1.2.0",
       "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+      "dev": true
     },
     "mississippi": {
       "version": "2.0.0",
@@ -5124,28 +5103,6 @@
       "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
       "dev": true
     },
-    "ng2-ace-editor": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/ng2-ace-editor/-/ng2-ace-editor-0.3.3.tgz",
-      "integrity": "sha512-LoIbAceDFHwoF5JOoHQZbTtzJDwP7c0JDC8oGVgQ1CaFQGxkIo9G4L5Kr8gErNfBieINHKotWzATHfI39nnVmQ==",
-      "requires": {
-        "ace-builds": "^1.2.9",
-        "brace": "^0.10.0"
-      }
-    },
-    "ng2-bs3-modal": {
-      "version": "0.13.0",
-      "resolved": "https://registry.npmjs.org/ng2-bs3-modal/-/ng2-bs3-modal-0.13.0.tgz",
-      "integrity": "sha512-rCxLpyTFXGpQOQCm32N4xGTN2roBsmIyUNQw6dFd/2yjVK+t7zmsFSO5IIuHioXAzTVGr4/LHFTOiz0JvJGnbg=="
-    },
-    "ng2-validation": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/ng2-validation/-/ng2-validation-4.2.0.tgz",
-      "integrity": "sha1-841EHT+36GIVUWZIAEWq/5rRHbs=",
-      "requires": {
-        "libphonenumber-js": "^0.4.5"
-      }
-    },
     "no-case": {
       "version": "2.3.2",
       "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
@@ -6027,9 +5984,9 @@
       }
     },
     "popper.js": {
-      "version": "1.14.7",
-      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.7.tgz",
-      "integrity": "sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ=="
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
     },
     "portfinder": {
       "version": "1.0.20",
@@ -6776,7 +6733,8 @@
     "regenerator-runtime": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+      "dev": true
     },
     "regex-cache": {
       "version": "0.4.4",
@@ -6961,11 +6919,6 @@
       "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
       "dev": true
     },
-    "rest-url-builder": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/rest-url-builder/-/rest-url-builder-1.0.6.tgz",
-      "integrity": "sha1-TmYdivTydMX/Li/EnfKjcS65NiI="
-    },
     "ret": {
       "version": "0.1.15",
       "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
@@ -7064,11 +7017,6 @@
         "pify": "^3.0.0"
       }
     },
-    "sax": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
-      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
-    },
     "schema-utils": {
       "version": "0.4.7",
       "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
@@ -8459,6 +8407,11 @@
         }
       }
     },
+    "vkbeautify": {
+      "version": "0.99.3",
+      "resolved": "https://registry.npmjs.org/vkbeautify/-/vkbeautify-0.99.3.tgz",
+      "integrity": "sha512-2ozZEFfmVvQcHWoHLNuiKlUfDKlhh4KGsy54U0UrlLMR1SO+XKAIDqBxtBwHgNrekurlJwE8A9K6L49T78ZQ9Q=="
+    },
     "vlq": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
@@ -8474,11 +8427,6 @@
         "indexof": "0.0.1"
       }
     },
-    "w3c-blob": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/w3c-blob/-/w3c-blob-0.0.1.tgz",
-      "integrity": "sha1-sM01KhpQ9RVWNCD/1YYflQ8dhbg="
-    },
     "watchpack": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
@@ -9906,20 +9854,6 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
     },
-    "xml2js": {
-      "version": "0.4.19",
-      "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
-      "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
-      "requires": {
-        "sax": ">=0.6.0",
-        "xmlbuilder": "~9.0.1"
-      }
-    },
-    "xmlbuilder": {
-      "version": "9.0.7",
-      "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
-      "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
-    },
     "xtend": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
diff --git a/gateway-admin-ui/package.json b/knox-homepage-ui/package.json
similarity index 75%
copy from gateway-admin-ui/package.json
copy to knox-homepage-ui/package.json
index aaa9b0d..6211f9c 100644
--- a/gateway-admin-ui/package.json
+++ b/knox-homepage-ui/package.json
@@ -1,12 +1,12 @@
 {
-  "name": "ng-knox-ui",
+  "name": "ng-knox-homepage",
   "version": "1.0.0",
   "license": "Apache-2.0",
   "scripts": {
-    "start": "ng serve --base-href /gateway/manager/admin-ui/ --deploy-url /gateway/manager/admin-ui/ --proxy-config proxy.conf.json",
+    "start": "ng serve --base-href /gateway/manager/admin-ui/ --deploy-url /gateway/manager/admin-ui/ --verbose=true",
     "build": "ng build",
     "build-prod": "ng build --prod",
-    "lint": "tslint \"admin-ui/**/*.ts\""
+    "lint": "tslint \"homepage/**/*.ts\""
   },
   "private": true,
   "dependencies": {
@@ -20,17 +20,14 @@
     "@angular/router": "^5.2.0",
     "angular2-datatable": "^0.6.0",
     "bootstrap": "^3.4.1",
-    "core-js": "^2.6.4",
+    "core-js": "^2.6.11",
     "jquery": "^3.4.1",
     "js-yaml": "^3.13.1",
-    "ng2-ace-editor": "0.3.3",
-    "ng2-bs3-modal": "^0.13.0",
-    "ng2-validation": "^4.2.0",
-    "popper.js": "^1.14.7",
-    "rest-url-builder": "^1.0.6",
+    "popper.js": "^1.16.1",
     "rxjs": "^5.5.2",
     "sweetalert": "^2.1.2",
     "ts-helpers": "^1.1.1",
+    "vkbeautify": "^0.99.3",
     "zone.js": "^0.8.29"
   },
   "devDependencies": {
@@ -38,7 +35,7 @@
     "@angular/compiler-cli": "^5.2.0",
     "@angular/language-service": "^5.2.0",
     "@types/jasmine": "~2.5.53",
-    "@types/jasminewd2": "~2.0.2",
+    "@types/jasminewd2": "^2.0.8",
     "@types/node": "~6.0.60",
     "codelyzer": "^4.1.0",
     "ts-node": "~3.2.0",
diff --git a/gateway-admin-ui/pom.xml b/knox-homepage-ui/pom.xml
similarity index 70%
copy from gateway-admin-ui/pom.xml
copy to knox-homepage-ui/pom.xml
index 4ba1d39..28fb71f 100644
--- a/gateway-admin-ui/pom.xml
+++ b/knox-homepage-ui/pom.xml
@@ -15,9 +15,9 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<project
-        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-        xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.knox</groupId>
@@ -25,14 +25,10 @@
         <version>1.4.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>gateway-admin-ui</artifactId>
-    <name>gateway-admin-ui</name>
-    <description>The gateway-admin-ui delivered with Knox.</description>
-
-    <properties>
-        <frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version>
-        <nodejs.version>v12.14.1</nodejs.version>
-    </properties>
+    <artifactId>knox-homepage-ui</artifactId>
+    <name>knox-homepage-ui</name>
+    <packaging>war</packaging>
+    <description>The Knox Home Page UI</description>
 
     <build>
         <plugins>
@@ -48,6 +44,22 @@
                 </configuration>
             </plugin>
             <plugin>
+               <groupId>org.apache.maven.plugins</groupId>
+               <artifactId>maven-war-plugin</artifactId>
+               <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <webResources>
+                        <resource>
+                            <directory>target/classes/homepage/app</directory>
+                            <targetPath>%2Fhome/</targetPath>
+                            <includes>
+                                <include>**</include>
+                            </includes>
+                        </resource>
+                    </webResources>
+               </configuration>
+            </plugin>
+            <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
                 <version>${frontend-maven-plugin.version}</version>
@@ -56,7 +68,7 @@
                 </configuration>
                 <executions>
                     <execution>
-                        <id>install node and npm</id>
+                        <id>knox-homepage-install-node-and-npm</id>
                         <goals>
                             <goal>install-node-and-npm</goal>
                         </goals>
@@ -65,7 +77,7 @@
                         </configuration>
                     </execution>
                     <execution>
-                        <id>npm install</id>
+                        <id>knox-homepage-npm-install</id>
                         <goals>
                             <goal>npm</goal>
                         </goals>
@@ -74,7 +86,7 @@
                         </configuration>
                     </execution>
                     <execution>
-                        <id>npm run lint</id>
+                        <id>knox-homepage-npm-run-lint</id>
                         <goals>
                             <goal>npm</goal>
                         </goals>
@@ -83,7 +95,7 @@
                         </configuration>
                     </execution>
                     <execution>
-                        <id>npm run build-prod</id>
+                        <id>knox-homepage-npm-run-build-prod</id>
                         <goals>
                             <goal>npm</goal>
                         </goals>
diff --git a/knox-homepage-ui/proxy.conf.json b/knox-homepage-ui/proxy.conf.json
new file mode 100644
index 0000000..0c245cf
--- /dev/null
+++ b/knox-homepage-ui/proxy.conf.json
@@ -0,0 +1,8 @@
+{
+  "/home/api": {
+    "target": "http://localhost:8443",
+    "secure": false,
+    "logLevel": "debug",
+    "changeOrigin": true
+  }
+}
\ No newline at end of file
diff --git a/knox-homepage-ui/src/main/webapp/%2F/WEB-INF/gateway.xml b/knox-homepage-ui/src/main/webapp/%2F/WEB-INF/gateway.xml
new file mode 100644
index 0000000..1e05c68
--- /dev/null
+++ b/knox-homepage-ui/src/main/webapp/%2F/WEB-INF/gateway.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<gateway>
+    <resource>
+        <role>home-api</role>
+        <pattern>*/**?**</pattern>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_CSRF</name>
+            <class>org.apache.knox.gateway.webappsec.filter.CSRFPreventionFilter</class>
+            <param>
+                <name>csrf.enabled</name>
+                <value>true</value>
+            </param>
+            <param>
+                <name>csrf.customheader</name>
+                <value>X-XSRF-Header</value>
+            </param>
+            <param>
+                <name>csrf.methodstoignore</name>
+                <value>GET,OPTIONS,HEAD</value>
+            </param>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_XFRAMEOPTIONS</name>
+            <class>org.apache.knox.gateway.webappsec.filter.XFrameOptionsFilter</class>
+            <param>
+                <name>xframe.options.enabled</name>
+                <value>true</value>
+            </param>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_XSSPROTECTION</name>
+            <class>org.apache.knox.gateway.webappsec.filter.XSSProtectionFilter</class>
+            <param>
+                <name>xss.protection.enabled</name>
+                <value>true</value>
+            </param>
+        </filter>
+        <filter>
+            <role>xforwardedheaders</role>
+            <name>XForwardedHeaderFilter</name>
+            <class>org.apache.knox.gateway.filter.XForwardedHeaderFilter</class>
+        </filter>
+        <filter>
+            <role>federation</role>
+            <name>SSOCookieProvider</name>
+            <class>org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter</class>
+        </filter>
+        <filter>
+            <role>pivot</role>
+            <name>jersey</name>
+            <class>org.glassfish.jersey.servlet.ServletContainer</class>
+            <param>
+                <name>jersey.config.server.provider.packages</name>
+                <value>org.apache.knox.gateway.service.metadata</value>
+            </param>
+        </filter>
+    </resource>
+</gateway>
diff --git a/knox-homepage-ui/src/main/webapp/%2F/WEB-INF/web.xml b/knox-homepage-ui/src/main/webapp/%2F/WEB-INF/web.xml
new file mode 100644
index 0000000..0a96df1
--- /dev/null
+++ b/knox-homepage-ui/src/main/webapp/%2F/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+	<servlet>
+		<servlet-name>knox-homepage-api-servlet</servlet-name>
+		<servlet-class>org.apache.knox.gateway.GatewayServlet</servlet-class>
+		<init-param>
+			<param-name>gatewayDescriptorLocation</param-name>
+			<param-value>/WEB-INF/gateway.xml</param-value>
+		</init-param>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>knox-homepage-api-servlet</servlet-name>
+		<url-pattern>/*</url-pattern>
+	</servlet-mapping>
+	<listener>
+		<listener-class>org.apache.knox.gateway.services.GatewayServicesContextListener</listener-class>
+	</listener>
+</web-app>
diff --git a/knox-homepage-ui/src/main/webapp/%2Fhome/WEB-INF/gateway.xml b/knox-homepage-ui/src/main/webapp/%2Fhome/WEB-INF/gateway.xml
new file mode 100644
index 0000000..d835ed2
--- /dev/null
+++ b/knox-homepage-ui/src/main/webapp/%2Fhome/WEB-INF/gateway.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<gateway>
+    <resource>
+        <role>homepage-ui</role>
+        <pattern>/?**</pattern>
+        <filter>
+            <role>xforwardedheaders</role>
+            <name>XForwardedHeaderFilter</name>
+            <class>org.apache.knox.gateway.filter.XForwardedHeaderFilter</class>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_CSRF</name>
+            <class>org.apache.knox.gateway.webappsec.filter.CSRFPreventionFilter</class>
+            <param>
+                <name>csrf.enabled</name>
+                <value>true</value>
+            </param>
+            <param>
+                <name>csrf.customheader</name>
+                <value>X-XSRF-Header</value>
+            </param>
+            <param>
+                <name>csrf.methodstoignore</name>
+                <value>GET,OPTIONS,HEAD</value>
+            </param>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_XFRAMEOPTIONS</name>
+            <class>org.apache.knox.gateway.webappsec.filter.XFrameOptionsFilter</class>
+            <param>
+                <name>xframe.options.enabled</name>
+                <value>true</value>
+            </param>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_XSSPROTECTION</name>
+            <class>org.apache.knox.gateway.webappsec.filter.XSSProtectionFilter</class>
+            <param>
+                <name>xss.protection.enabled</name>
+                <value>true</value>
+            </param>
+        </filter>
+        <filter>
+            <role>federation</role>
+            <name>SSOCookieProvider</name>
+            <class>org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter</class>
+        </filter>
+
+    </resource>
+    <resource>
+        <role>homepage-ui</role>
+        <pattern>/**?**</pattern>
+        <filter>
+            <role>xforwardedheaders</role>
+            <name>XForwardedHeaderFilter</name>
+            <class>org.apache.knox.gateway.filter.XForwardedHeaderFilter</class>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_CSRF</name>
+            <class>org.apache.knox.gateway.webappsec.filter.CSRFPreventionFilter</class>
+            <param>
+                <name>csrf.enabled</name>
+                <value>true</value>
+            </param>
+            <param>
+                <name>csrf.customheader</name>
+                <value>X-XSRF-Header</value>
+            </param>
+            <param>
+                <name>csrf.methodstoignore</name>
+                <value>GET,OPTIONS,HEAD</value>
+            </param>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_XFRAMEOPTIONS</name>
+            <class>org.apache.knox.gateway.webappsec.filter.XFrameOptionsFilter</class>
+            <param>
+                <name>xframe.options.enabled</name>
+                <value>true</value>
+            </param>
+        </filter>
+        <filter>
+            <role>webappsec</role>
+            <name>WebAppSec_XSSPROTECTION</name>
+            <class>org.apache.knox.gateway.webappsec.filter.XSSProtectionFilter</class>
+            <param>
+                <name>xss.protection.enabled</name>
+                <value>true</value>
+            </param>
+        </filter>
+        <filter>
+            <role>federation</role>
+            <name>SSOCookieProvider</name>
+            <class>org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter</class>
+        </filter>
+    </resource>
+</gateway>
diff --git a/knox-homepage-ui/src/main/webapp/%2Fhome/WEB-INF/web.xml b/knox-homepage-ui/src/main/webapp/%2Fhome/WEB-INF/web.xml
new file mode 100644
index 0000000..03951c8
--- /dev/null
+++ b/knox-homepage-ui/src/main/webapp/%2Fhome/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+	<filter>
+		<filter-name>knox-homepage-filter</filter-name>
+		<filter-class>org.apache.knox.gateway.GatewayServlet</filter-class>
+		<init-param>
+			<param-name>gatewayDescriptorLocation</param-name>
+			<param-value>/WEB-INF/gateway.xml</param-value>
+		</init-param>
+	</filter>
+	<filter-mapping>
+		<filter-name>knox-homepage-filter</filter-name>
+		<url-pattern>/*</url-pattern>
+	</filter-mapping>
+	<listener>
+		<listener-class>org.apache.knox.gateway.services.GatewayServicesContextListener</listener-class>
+	</listener>
+</web-app>
diff --git a/knox-homepage-ui/tslint.json b/knox-homepage-ui/tslint.json
new file mode 100644
index 0000000..ba6f13d
--- /dev/null
+++ b/knox-homepage-ui/tslint.json
@@ -0,0 +1,94 @@
+{
+  "rulesDirectory": [
+    "node_modules/codelyzer"
+  ],
+  "rules": {
+    "class-name": true,
+    "comment-format": [
+      true,
+      "check-space"
+    ],
+    "curly": true,
+    "eofline": true,
+    "forin": true,
+    "indent": [
+      true,
+      "spaces"
+    ],
+    "label-position": true,
+    "max-line-length": [
+      true,
+      140
+    ],
+    "member-access": false,
+    "member-ordering": [
+      true,
+      "static-before-instance",
+      "variables-before-functions"
+    ],
+    "no-arg": true,
+    "no-bitwise": true,
+    "no-console": false,
+    "no-construct": true,
+    "no-debugger": true,
+    "no-duplicate-variable": true,
+    "no-empty": false,
+    "no-eval": true,
+    "no-inferrable-types": true,
+    "no-shadowed-variable": true,
+    "no-string-literal": false,
+    "no-switch-case-fall-through": true,
+    "no-trailing-whitespace": true,
+    "no-unused-expression": true,
+    "no-var-keyword": true,
+    "object-literal-sort-keys": false,
+    "one-line": [
+      true,
+      "check-open-brace",
+      "check-catch",
+      "check-else",
+      "check-whitespace"
+    ],
+    "quotemark": [
+      true,
+      "single"
+    ],
+    "radix": true,
+    "semicolon": true,
+    "triple-equals": [
+      true,
+      "allow-null-check"
+    ],
+    "typedef-whitespace": [
+      true,
+      {
+        "call-signature": "nospace",
+        "index-signature": "nospace",
+        "parameter": "nospace",
+        "property-declaration": "nospace",
+        "variable-declaration": "nospace"
+      }
+    ],
+    "variable-name": false,
+    "whitespace": [
+      true,
+      "check-branch",
+      "check-decl",
+      "check-operator",
+      "check-separator",
+      "check-type"
+    ],
+
+    "directive-selector": [true, "attribute", "app", "camelCase"],
+    "component-selector": [true, "element", "app", "kebab-case"],
+    "use-input-property-decorator": true,
+    "use-output-property-decorator": true,
+    "use-host-property-decorator": true,
+    "no-input-rename": false,
+    "no-output-rename": true,
+    "use-life-cycle-interface": true,
+    "use-pipe-transform-interface": true,
+    "component-class-suffix": true,
+    "directive-class-suffix": true
+  }
+}
diff --git a/pom.xml b/pom.xml
index 9b02053..0c17b91 100644
--- a/pom.xml
+++ b/pom.xml
@@ -139,6 +139,8 @@
         <module>gateway-release-common</module>
         <module>gateway-topology-simple</module>
         <module>gateway-cm-integration</module>
+        <module>gateway-service-metadata</module>
+        <module>knox-homepage-ui</module>
     </modules>
 
     <properties>
@@ -189,6 +191,7 @@
         <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
         <findsecbugs-plugin.version>1.10.1</findsecbugs-plugin.version>
         <forbiddenapis.version>2.7</forbiddenapis.version>
+        <frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version>
         <gson.version>2.8.6</gson.version>
         <groovy.version>3.0.1</groovy.version>
         <guava.version>28.2-jre</guava.version>
@@ -230,9 +233,11 @@
         <maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
         <maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version>
         <maven-pmd-plugin.version>3.12.0</maven-pmd-plugin.version>
+        <maven-war-plugin.version>3.2.3</maven-war-plugin.version>
         <metrics.version>4.1.3</metrics.version>
         <mina.version>2.0.21</mina.version>
         <nimbus-jose-jwt.version>8.8</nimbus-jose-jwt.version>
+        <nodejs.version>v12.14.1</nodejs.version>
         <okhttp.version>2.7.5</okhttp.version>
         <opensaml.version>3.4.3</opensaml.version>
         <pac4j.version>3.8.3</pac4j.version>
@@ -421,6 +426,10 @@
                         <exclude>**/admin-ui/**/*.js</exclude>
                         <exclude>**/admin-ui/**/*.css</exclude>
                         <exclude>**/admin-ui/**/*.html</exclude>
+                        <exclude>**/knox-homepage-ui/**/*.json</exclude>
+                        <exclude>**/knox-homepage-ui/**/*.js</exclude>
+                        <exclude>**/knox-homepage-ui/**/*.css</exclude>
+                        <exclude>**/knox-homepage-ui/**/*.html</exclude>
                         <exclude>atlassian-ide-plugin.xml</exclude>
                         <exclude>**/PULL_REQUEST_TEMPLATE*</exclude>
                         <exclude>**/new-service-definition-template.xml</exclude>
@@ -661,6 +670,11 @@
                 </executions>
             </plugin>
             <plugin>
+               <groupId>org.apache.maven.plugins</groupId>
+               <artifactId>maven-war-plugin</artifactId>
+               <version>${maven-war-plugin.version}</version>
+            </plugin>
+            <plugin>
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
                 <version>${jacoco-maven-plugin.version}</version>
@@ -1165,6 +1179,17 @@
                 <artifactId>gateway-cm-integration</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.knox</groupId>
+                <artifactId>gateway-service-metadata</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.knox</groupId>
+                <artifactId>knox-homepage-ui</artifactId>
+                <version>${project.version}</version>
+                <type>war</type>
+            </dependency>
 
             <dependency>
                 <groupId>org.glassfish.jersey.containers</groupId>