From 47561f2491423be585ff2ef2d802a1de82823f76 Mon Sep 17 00:00:00 2001 From: Jakub Hadvig Date: Fri, 27 Oct 2017 17:55:25 +0200 Subject: [PATCH] Check 'auth' field when displaying .dockercfg config --- app/scripts/services/secrets.js | 113 +++++++++++++++++++++----------- dist/scripts/scripts.js | 74 ++++++++++----------- 2 files changed, 110 insertions(+), 77 deletions(-) diff --git a/app/scripts/services/secrets.js b/app/scripts/services/secrets.js index 8dbba3bdc1..4971e85207 100644 --- a/app/scripts/services/secrets.js +++ b/app/scripts/services/secrets.js @@ -1,7 +1,7 @@ 'use strict'; angular.module("openshiftConsole") - .factory("SecretsService", function(){ + .factory("SecretsService", function($filter, Logger, NotificationsService){ var groupSecretsByType = function(secrets) { var secretsByType = { @@ -28,67 +28,104 @@ angular.module("openshiftConsole") return secretsByType; }; - var decodeDockercfg = function(encodedData) { - var decodedSecretData = { - auths: {} - }; - var decodedData = JSON.parse(window.atob(encodedData)); - _.each(decodedData, function(data, serverName) { - decodedSecretData.auths[serverName] = { - username: data.username, - password: data.password, - email: data.email - }; + var handleDecodeException = function(error, encodedStringType) { + NotificationsService.addNotification({ + type: "error", + message: 'Base64-encoded ' + encodedStringType + ' string could not be decoded.', + details: $filter('getErrorDetails')(error) }); - return decodedSecretData; + Logger.error('Base64-encoded ' + encodedStringType + ' string could not be decoded.', error); + }; + + var getServerParams = function(serverData) { + var params = _.pick(serverData, ['email', 'username', 'password']); + if (serverData.auth) { + try { + // Decode Base64-encoded username:password string. + var setParams = _.spread(function(username, password) { + params.username = username; + params.password = password; + }); + setParams(_.split(window.atob(serverData.auth), ':', 2)); + } catch(e) { + handleDecodeException(e, 'username:password'); + return; + } + } + return params; }; - var decodeDockerconfigjson = function(encodedData) { + // decodeDockerConfig handles both Docker configuration file formats, which are: + // - .dockercfg + // { + // "auths": { + // "https://index.docker.io/v1/": { + // "auth": "dGVzdHVzZXI6dGVzdHB3", + // "email": "jhadvig@test.com" + // } + // } + // } + // + // - .dockerconfigjson + // { + // "auths": { + // "https://index.docker.io/v1/": { + // "auth": "dGVzdHVzZXI6dGVzdHB3", + // "email": "mail@test.com" + // } + // } + // } + // + var decodeDockerConfig = function(encodedData, configType) { + var decodedData; var decodedSecretData = { auths: {} }; - var decodedData = JSON.parse(window.atob(encodedData)); - _.each(decodedData.auths, function(data, serverName) { - if (!data.auth) { - decodedSecretData.auths[serverName] = data; - return; - } - var usernamePassword = window.atob(data.auth).split(":"); - decodedSecretData.auths[serverName] = { - username: usernamePassword[0], - password: usernamePassword[1], - email: data.email - }; - }); + try { + decodedData = JSON.parse(window.atob(encodedData)); + } catch(e) { + handleDecodeException(e, configType); + } - if (decodedData.credsStore) { - decodedSecretData.credsStore = decodedData.credsStore; + if (configType === ".dockercfg") { + _.each(decodedData, function(serverData, serverName) { + decodedSecretData.auths[serverName] = getServerParams(serverData); + }); + } else { + _.each(decodedData.auths, function(serverData, serverName) { + if (!serverData.auth) { + decodedSecretData.auths[serverName] = serverData; + return; + } + decodedSecretData.auths[serverName] = getServerParams(serverData); + }); + + if (decodedData.credsStore) { + decodedSecretData.credsStore = decodedData.credsStore; + } } return decodedSecretData; }; + var decodeSecretData = function(secretData) { var nonPrintable = {}; - var decodedSecret = _.mapValues(secretData, function(data, paramName) { + var decodedSecret = _.mapValues(secretData, function(data, configType) { var decoded, isNonPrintable; - switch (paramName) { - case ".dockercfg": - return decodeDockercfg(data); - case ".dockerconfigjson": - return decodeDockerconfigjson(data); - default: + if (configType === ".dockercfg" || configType === ".dockerconfigjson") { + return decodeDockerConfig(data, configType); + } else { decoded = window.atob(data); // Allow whitespace like newlines and tabs, but detect other // non-printable characters in the unencoded data. // http://stackoverflow.com/questions/1677644/detect-non-printable-characters-in-javascript isNonPrintable = /[\x00-\x09\x0E-\x1F]/.test(decoded); if (isNonPrintable) { - nonPrintable[paramName] = true; + nonPrintable[configType] = true; return data; } - return decoded; } }); diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index d1521259ad..845a114474 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -3168,32 +3168,37 @@ message: null }; } }; -}), angular.module("openshiftConsole").factory("SecretsService", function() { -var e = function(e) { -var t = { -auths: {} -}, n = JSON.parse(window.atob(e)); -return _.each(n, function(e, n) { -t.auths[n] = { -username: e.username, -password: e.password, -email: e.email -}; -}), t; -}, t = function(e) { -var t = { +}), angular.module("openshiftConsole").factory("SecretsService", [ "$filter", "Logger", "NotificationsService", function(e, t, n) { +var a = function(a, r) { +n.addNotification({ +type: "error", +message: "Base64-encoded " + r + " string could not be decoded.", +details: e("getErrorDetails")(a) +}), t.error("Base64-encoded " + r + " string could not be decoded.", a); +}, r = function(e) { +var t = _.pick(e, [ "email", "username", "password" ]); +if (e.auth) try { +_.spread(function(e, n) { +t.username = e, t.password = n; +})(_.split(window.atob(e.auth), ":", 2)); +} catch (e) { +return void a(e, "username:password"); +} +return t; +}, o = function(e, t) { +var n, o = { auths: {} -}, n = JSON.parse(window.atob(e)); -return _.each(n.auths, function(e, n) { -if (e.auth) { -var a = window.atob(e.auth).split(":"); -t.auths[n] = { -username: a[0], -password: a[1], -email: e.email }; -} else t.auths[n] = e; -}), n.credsStore && (t.credsStore = n.credsStore), t; +try { +n = JSON.parse(window.atob(e)); +} catch (e) { +a(e, t); +} +return ".dockercfg" === t ? _.each(n, function(e, t) { +o.auths[t] = r(e); +}) : (_.each(n.auths, function(e, t) { +e.auth ? o.auths[t] = r(e) : o.auths[t] = e; +}), n.credsStore && (o.credsStore = n.credsStore)), o; }; return { groupSecretsByType: function(e) { @@ -3220,24 +3225,15 @@ t.other.push(e); } }), t; }, -decodeSecretData: function(n) { -var a = {}, r = _.mapValues(n, function(n, r) { -var o; -switch (r) { -case ".dockercfg": -return e(n); - -case ".dockerconfigjson": -return t(n); - -default: -return o = window.atob(n), /[\x00-\x09\x0E-\x1F]/.test(o) ? (a[r] = !0, n) : o; -} +decodeSecretData: function(e) { +var t = {}, n = _.mapValues(e, function(e, n) { +var a; +return ".dockercfg" === n || ".dockerconfigjson" === n ? o(e, n) : (a = window.atob(e), /[\x00-\x09\x0E-\x1F]/.test(a) ? (t[n] = !0, e) : a); }); -return r.$$nonprintable = a, r; +return n.$$nonprintable = t, n; } }; -}), angular.module("openshiftConsole").factory("ServicesService", [ "$filter", "$q", "DataService", function(e, t, n) { +} ]), angular.module("openshiftConsole").factory("ServicesService", [ "$filter", "$q", "DataService", function(e, t, n) { var a = "service.alpha.openshift.io/dependencies", r = e("annotation"), o = function(e) { var t = r(e, a); if (!t) return null;