Azure Extensions

This repository contains user scripts for enhancing your Azure Portal experience.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Azure Extensions
// @namespace    http://tampermonkey.net/
// @version      2024-09-17
// @description  This repository contains user scripts for enhancing your Azure Portal experience.
// @author       Toni Hoffmann, Dominik Weber
// @match        https://portal.azure.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=azure.com
// @grant        none
// ==/UserScript==

// Initial Author: Dominik Weber
function increaseKeyVaultTextfield() {
  const observer = new MutationObserver(() => {
    const element = document.getElementsByClassName('azc-textarea')[0];
    if (element) {
      element.style.height = '300px';
    }
  });
  observer.observe(document.body, { childList: true });
}

// Initial Author: Toni Hoffmann
function extendAutoExpandNavigationGroupings() {
  const observer = new MutationObserver(() => {
    // Get all groupings
    let groupings = Array.from(document.querySelectorAll('button.azc-listView-collapsible-groupheader'));

    // Filter groupings to only those that contain the relevant SVG child
    let relevantGroupings = groupings.filter((grouping) => {
      let svg = grouping.querySelector('svg');
      return svg && svg.firstChild && svg.firstChild.href.baseVal.includes('#FxSymbol0-034');
    });

    // Print the count of relevant groupings
    console.log(`Found ${relevantGroupings.length} relevant groupings`);

    // Click through each relevant grouping
    relevantGroupings.forEach((grouping) => {
      grouping.click();
    });
  });
  observer.observe(document.body, { childList: true });
}

// Initial Author: Toni Hoffmann
function showSecretsInOverview() {
  const observer = new MutationObserver(() => {
    // check if the page is the keyvault secrets page
    const isKeyVaultPage =
      window.location.href.includes('/providers/Microsoft.KeyVault/vaults/') &&
      window.location.href.endsWith('/secrets');
    if (!isKeyVaultPage) {
      return;
    }
    if (hasButtonAlreadyOnFooter()) {
      return;
    }
    if (!footerHasLoaded()) {
      return; 
    }

    function loadKeyvaultContent(keyvault, secret, callback) {
      const token = JSON.parse(
        sessionStorage.getItem(
          Object.keys(sessionStorage).find((key) => key.includes('https://vault.azure.net/user_impersonation'))
        )
      ).secret;
      var xhr = new XMLHttpRequest();
      xhr.open('GET', `https://${keyvault}.vault.azure.net/secrets/${secret}?api-version=7.0`, true);
      xhr.setRequestHeader('Authorization', `Bearer ${token}`); // Set the token as a Bearer token in the Authorization header
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
          const content = JSON.parse(xhr.responseText);
          // console.log(content.value);
          callback(content.value);
        }
      };
      xhr.send();
    }

    function showSecrets() {
      // get current url
      const keyVaultName = window.location.href.split('/vaults/')[1].split('/secrets')[0];

      //  Rename the title
      Array.from(
        Array.from(document.querySelectorAll('table.azc-grid-tableHeader tr'))[0].children
      ).pop().firstChild.innerHTML = 'Secret';

      const secretTableRows = Array.from(document.querySelectorAll('table.azc-grid-full tr'));
      // for of
      for (const row of secretTableRows) {
        const secretName = row.children[0].innerText;
        const lastTD = row.children[row.children.length - 1];
        //  lastTD.innerHTML = secretName;
        loadKeyvaultContent(keyVaultName, secretName, function (secret) {
          lastTD.innerHTML = secret;
        });
      }
    }

    // TODO move this to toolbar, but this caused some issues at the moment
    function addButtonToFooter() {
      const footerBar = document.querySelector('.ext-feedback-positioning');
      // add button
      const button = document.createElement('div');
      button.innerHTML = '<div id="custom-show-secret-button" role="button" style="margin-left: 10px; color: var(--colorLink);">Show Secrets</div>';
      button.onclick = function () {
        showSecrets();
      };
      footerBar.appendChild(button);
    }

    function hasButtonAlreadyOnFooter() {
      return document.querySelector('#custom-show-secret-button');
    }

    function footerHasLoaded(){
      return document.querySelector('.ext-feedback-positioning .azc-formElementContainer').innerText.includes('Give feedback');
    }

    addButtonToFooter();
  });
  observer.observe(document.body, { childList: true });
}

(function () {
  'use strict';
  // Choose wich extensions you want to extend:
  extendAutoExpandNavigationGroupings();
  increaseKeyVaultTextfield();
  showSecretsInOverview();
})();