<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gurucharan Subramani</title>
    <description>The latest articles on Forem by Gurucharan Subramani (@gurucharan94).</description>
    <link>https://forem.com/gurucharan94</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F33397%2Fc95d99bb-d553-464a-a1ff-a6a359444c98.jpeg</url>
      <title>Forem: Gurucharan Subramani</title>
      <link>https://forem.com/gurucharan94</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gurucharan94"/>
    <language>en</language>
    <item>
      <title>Getting Started with LightHouse CI - Part 2</title>
      <dc:creator>Gurucharan Subramani</dc:creator>
      <pubDate>Wed, 01 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/gurucharan94/getting-started-with-lighthouse-ci-part-2-358p</link>
      <guid>https://forem.com/gurucharan94/getting-started-with-lighthouse-ci-part-2-358p</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/gurucharan94/getting-started-with-lighthouse-ci-part-1-io1"&gt;previous part (Part 1)&lt;/a&gt;, we learnt about how to get started with Lighthouse CI, what are the different commands available, how to run your first scan and compare the results against a baseline. In this part (Part 2), we continue to look at how to set up a Lighthouse server on Azure so that we can upload the scan results, see trends and compare the scores of your site at different points in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Command
&lt;/h2&gt;

&lt;p&gt;We ran our scans and we have validated that the scores are above our baseline. You know what would be nice? The ability to see the results on a dashboard with historic data from every scan and ability to link them to a specific commit and build/release in your pipeline. This is exactly what the Lighthouse server enables us to do. To install the Lighthouse server, run &lt;code&gt;npm install @lhci/server&lt;/code&gt;and then run &lt;code&gt;lhci server&lt;/code&gt; with the below configuration in place to start the server locally on port 9001 which stores the result in a SQLLite Database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "server": {
      "port": 9001,
      "storage": {
        "storageMethod": "sql",
        "sqlDialect": "sqllite",
        "sqlDatabasePath": "lhci.db"
      }
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you now visit port 9001, you will be greeted with a friendly page asking you to run the &lt;code&gt;lhci wizard&lt;/code&gt; command to set-up the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caution:&lt;/strong&gt; Lighthouse server does not support authentication/authorization now but that is &lt;a href="https://github.com/GoogleChrome/lighthouse-ci/issues/85"&gt;being worked on&lt;/a&gt; and so please be aware of the risks here.&lt;/p&gt;

&lt;p&gt;Before we get to the wizard part, I’ll show you how to run a publicly available Lighthouse server on Azure. If this whole Azure thing is not important to you, feel free to skip the next bits and head straight over to the Wizard Section or head to &lt;a href="https://github.com/GoogleChrome/lighthouse-ci/tree/master/docs/recipes"&gt;the cloud recipes&lt;/a&gt; for instructions on running the server on a different cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lighthouse Server on Azure
&lt;/h3&gt;

&lt;p&gt;There is a &lt;a href="https://hub.docker.com/r/patrickhulce/lhci-server/"&gt;docker image&lt;/a&gt; available for Lighthouse Server. This means that you can make use of Azure Web App for Containers and pass in configuration as environment variables using App Settings.&lt;/p&gt;

&lt;p&gt;Log in to the Azure Portal, create a new &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/containers/"&gt;Azure Web App for Containers&lt;/a&gt; to run the &lt;code&gt;patrickhulce/lhci-server&lt;/code&gt; image from DockerHub. The next step is to create a &lt;a href="https://docs.microsoft.com/en-us/azure/postgresql/"&gt;Postgres Database on Azure&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that the resources are created, let’s update their configurations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once the database is created, go to Connection Security and ensure that ‘Enforce SSL connection’ is set to DISABLED and the ‘Allow access to Azure services’ is set to ON. Take a look at the &lt;a href="https://github.com/GoogleChrome/lighthouse-ci/issues/160"&gt;related issue on GitHub&lt;/a&gt; to understand why SSL is not supported at the moment.&lt;/li&gt;
&lt;li&gt;The next step is to add the below snippet to the application settings. Take note of the &lt;a href="https://github.com/MicrosoftDocs/azure-docs/issues/6371#issuecomment-376722771"&gt;Postgres connection string&lt;/a&gt;. There is a weird &lt;code&gt;%40&lt;/code&gt; thing going on and also we use the default database called &lt;code&gt;postgres&lt;/code&gt;. You can, of course, use a Postgres client to create a new database and use that in the connection string.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "name": "LHCI_NO_LIGHTHOUSERC",
    "value": "1",
    "slotSetting": false
  },
  {
    "name": "LHCI_STORAGE__SQL_CONNECTION_SSL",
    "value": "0",
    "slotSetting": false
  },
  {
    "name": "LHCI_STORAGE__SQL_CONNECTION_URL",
    "value": "postgresql://username%40myserver:password@myserver.postgres.database.azure.com:5432/postgres",
    "slotSetting": false
  },
  {
    "name": "LHCI_STORAGE__SQL_DIALECT",
    "value": "postgres",
    "slotSetting": false
  },
]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once you have all this configuration in place, you should be able to see the Lighthouse server home page prompting you to run the wizard to set up your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I1MsaUEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-server.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I1MsaUEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-server.png" alt="Lighthouse CI Server Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wizard Command
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, Lighthouse Server does not support any form of authentication or authorization as of now and consequently, there is no project management UI either. To set up a project on the server, run &lt;code&gt;lhci wizard&lt;/code&gt; on your command prompt, complete the wizard and take note of the GUID token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WvUpo1V6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-wizard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WvUpo1V6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-wizard.png" alt="Lighthouse CI Wizard Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have configured a project on the server, you can update your Lighthouse configuration file as shown below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "upload": {
    "target": "lhci",
    "token": "your-token-xxxx-yyyy-zzzz",
    "serverBaseUrl": "https://myserver.azurewebsites.net/"
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Upload Command
&lt;/h2&gt;

&lt;p&gt;Now you have all the configuration in place and ready to upload results to your server. You can do that with the &lt;code&gt;lhci upload&lt;/code&gt; command. When you run the command, you will get an error message saying &lt;code&gt;Error: Unable to determine current hash with git rev-parse HEAD&lt;/code&gt;. Lighthouse CI requires certain metadata before pushing the results to the server and tries to infer that from the git repository. They call this Build Context and you can read more on this &lt;a href="https://github.com/GoogleChrome/lighthouse-ci/blob/master/docs/cli.md#build-context"&gt;from their docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To push your results to the server, initialize a git repo, commit your changes and then you can upload your results to the server using the &lt;code&gt;lhci upload&lt;/code&gt; command. Once you upload multiple results, you can then compare the scores against two different versions, see what changed and understand general trends in your Lighthouse scores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LpvbSwLD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-results.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LpvbSwLD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-results.png" alt="Lighthouse Server Results Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Autorun Command
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;lhci autorun&lt;/code&gt; command combines the healthcheck, collect, assert and upload commands depending on the configuration. I find this very useful and it is nice that this convenient wrapper is available out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Azure Devops Extension
&lt;/h2&gt;

&lt;p&gt;Right now everything works perfect on my machine but still requires some work to get it running successfully inside my deployment pipelines. All my pipelines are hosted on &lt;a href="https://azure.microsoft.com/en-in/services/devops/"&gt;Azure Devops&lt;/a&gt; and so I built &lt;a href="https://marketplace.visualstudio.com/items?itemName=gurucharan.lighthouse-ci"&gt;an extension that features a custom build and release&lt;/a&gt;task using NodeJS that helps you run Lighthouse CI inside Azure Pipelines.&lt;/p&gt;

&lt;p&gt;You specify the command you want to run, point to the configuration file and the extension overrides the build context with relevant predefined variables available inside Azure Pipelines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8zmaFw8s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/GuruCharan94/azure-devops-extensions/master/lighthouse-ci/images/demo-pipeline.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8zmaFw8s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/GuruCharan94/azure-devops-extensions/master/lighthouse-ci/images/demo-pipeline.png" alt="Azure Pipelines Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this 2 part Lighthouse series, you have installed Lighthouse-ci CLI, learnt how to configure it, set up the Lighthouse server on Azure and have a good understanding of the different commands (healthcheck, collect, assert, upload and autorun) that is available to you. Once the results are pushed to the server, you would then compare scores, see trends and compare the scores of your site at different points in time.&lt;/p&gt;

&lt;p&gt;Right now, I am happy with all the features available considering that this is still in 0.x.y version. Once the server supports authentication and includes a project management UI, then it is ready for prime time. But overall, looks very good to me.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>seo</category>
      <category>security</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Getting Started with LightHouse CI - Part 1</title>
      <dc:creator>Gurucharan Subramani</dc:creator>
      <pubDate>Wed, 01 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/gurucharan94/getting-started-with-lighthouse-ci-part-1-io1</link>
      <guid>https://forem.com/gurucharan94/getting-started-with-lighthouse-ci-part-1-io1</guid>
      <description>&lt;p&gt;This blog post shows you how to get started with Lighthouse CI, what are the different configurations and commands available to you and how to run your first scan and compare the results against a baseline that you specify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GoogleChrome/lighthouse-ci"&gt;Lighthouse CI&lt;/a&gt; is a node CLI that has a set of commands that make continuously running, asserting, saving, and retrieving &lt;a href="https://dev.to/gurucharan94/test-performance-security-and-accessibility-concerns-of-your-website-with-google-lighthouse-2ee9-temp-slug-8216156"&gt;Lighthouse results&lt;/a&gt; as easy as possible. Lighthouse CI is made up of 2 components, the node CLI to run the different commands and the node server where results are uploaded and stored for you to compare the scores and see trends of individual metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The easiest way to get started with Lighthouse CI is by installing the node CLI globally on your computer. To do this, run &lt;code&gt;npm install -g @lhci/cli&lt;/code&gt;. Once the CLI is installed successfully, you can invoke it and understand the options available to you by running &lt;code&gt;lhci --help&lt;/code&gt;. You should now see 6 commands available to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Each of the individual commands have accept some arguments. Run the help command &lt;code&gt;lhci &amp;lt;commandname&amp;gt;--help&lt;/code&gt; to understand what configuration options are available to you. Lighthouse CI uses the &lt;a href="https://github.com/yargs/yargs/blob/v12.0.5/docs/api.md#envprefix"&gt;YARGS API&lt;/a&gt; to read configuration and that means you can pass arguments to the CLI in multiple ways and are read in the below order of precedence.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CLI arguments&lt;/li&gt;
&lt;li&gt;Environment Variables&lt;/li&gt;
&lt;li&gt;Configuration Files&lt;/li&gt;
&lt;li&gt;Default Settings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://github.com/GoogleChrome/lighthouse-ci/blob/master/docs/configuration.md"&gt;GitHub documentation&lt;/a&gt; goes into great detail with examples of the different configuration options. Throughout this post, I will be using a configuration file to pass arguments. The JSON file structure has the below format and is called &lt;code&gt;lighthouserc.json&lt;/code&gt; and is at the root of the current working directory.&lt;/p&gt;

&lt;p&gt;The final configuration file is available &lt;a href="https://github.com/GuruCharan94/lighthouse-ci-demo"&gt;in this repository on GitHub&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "ci": {
    "collect": {
      // collect options here
    },
    "assert": {
      // assert options here
    },
    "upload": {
      // upload options here
    },
    "server": {
      // server options here
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let us take a look at the different commands available to us and what they accomplish and how to specify the proper configuration under the relevant sections of the configuration file.&lt;/p&gt;

&lt;h2&gt;
  
  
  HealthCheck Command
&lt;/h2&gt;

&lt;p&gt;The first command is the health check. The &lt;code&gt;healthcheck&lt;/code&gt; command performs a set of checks to ensure a valid configuration and very useful when setting up Lighthouse CI initially.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;lhci healthcheck&lt;/code&gt; on the command prompt and then depending on the contents of your configuration file, you will see different types of checks being executed. Here is the result of a successful health check.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cCCrMrUF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-healthcheck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cCCrMrUF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/lhci/lhci-healthcheck.png" alt="Lighthouse CI Health Check Results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should execute the &lt;code&gt;healthcheck&lt;/code&gt; multiple times as you build up your configuration to understand what checks are included and how the results differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collect Command
&lt;/h2&gt;

&lt;p&gt;Next and perhaps the most important command is the &lt;code&gt;collect&lt;/code&gt; command runs Lighthouse scan the specified number of times on and “collects” the results in a &lt;code&gt;.lighthouseci/&lt;/code&gt; folder relative to the current working directory. Run &lt;code&gt;lhci collect --help&lt;/code&gt; to see the different configuration options available and how it maps to the JSON file below.&lt;/p&gt;

&lt;p&gt;The collect command allows you to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run scans on multiple URL’s and also scan each URL multiple times.&lt;/li&gt;
&lt;li&gt;Run a puppeteer script so that you can log in to the website and then scan pages that require authentication. Note that you will need to install the puppeteer package from NPM.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "collect": {
    "method": "node",
    "additive": false, // Clean up previous lighthouse runs
    "headful": false, // Headless Chrome
    "numberOfRuns": 3, // 3 runs per each URL
    "puppeteerScript": "./fake-login.js", // Run this script before auditing below URLs'. Usually Login Scripts.
    "url": [
      "https://www.gurucharan.in/",
      "https://www.gurucharan.in/about/"
    ],
    "settings": {
      "config-path": "./light-house-config.js" // Flags to pass to lightHouse
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With the configuration in place, you can now run &lt;code&gt;lhci collect&lt;/code&gt; and if everything is successful, you will see the Lighthouse results inside the &lt;code&gt;.lighthouseci/&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assert Command
&lt;/h2&gt;

&lt;p&gt;We have successfully run our Lighthouse scans and “collected” our results. The next logical step is to run a bunch of tests that verify that the results meet expectations. As with the other commands, below is a snippet of the configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "assert": {
    "preset": "lighthouse:no-pwa",
    "assertions": {
      "categories:performance": ["warn", {"aggregationMethod": "optimistic", "minScore": 0.70}],
      "categories:accessibility": ["warn", {"aggregationMethod": "optimistic", "minScore": 0.90}]
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;One thing that needs mentioning is that the assertion operation supports a wide range of configurations. You can test against built-in &lt;code&gt;presets&lt;/code&gt; or assert against individual categories of Lighthouse results and even set baselines on every metric in the scan results.&lt;/p&gt;

&lt;p&gt;When checking the results of runs against multiple URLs, different assertions can be made for different URL patterns using regular expressions. Definitely take a look at the &lt;a href="https://github.com/GoogleChrome/lighthouse-ci/blob/master/docs/assertions.md"&gt;documentation for the assert operation&lt;/a&gt; where other options are documented.&lt;/p&gt;

&lt;p&gt;In this example, we run tests against the built-in preset which ignores PWA (Progressive Web App) evaluation. We also assert against said performance and accessibility against a baseline score of 0.70 for performance and 0.90 for accessibility. Since we ran the scan against each URL thrice, we specify optimistic as aggregation method which instructs Lighthouse to take the score that has the highest chance of success.&lt;/p&gt;

&lt;p&gt;This post showed the basics of getting started with Lighthouse CI and how to run your first scan and compare results against a baseline. In &lt;a href="https://www.gurucharan.in/web/nodejs/lighthouse-ci-the-complete-guide-part-2/"&gt;part 2&lt;/a&gt;, we continue to look at how to set up a Lighthouse server so that we can upload the scan results, see trends and compare the scores of your site at different points in time.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>seo</category>
      <category>security</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Five CosmosDB tools that make you productive</title>
      <dc:creator>Gurucharan Subramani</dc:creator>
      <pubDate>Thu, 10 Oct 2019 00:00:00 +0000</pubDate>
      <link>https://forem.com/gurucharan94/five-cosmosdb-tools-that-make-you-productive-10n3</link>
      <guid>https://forem.com/gurucharan94/five-cosmosdb-tools-that-make-you-productive-10n3</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction" rel="noopener noreferrer"&gt;Azure Cosmos DB&lt;/a&gt; is Microsoft’s globally distributed, multi-model, NoSQL database service. Cosmos DB enables you to elastically and independently scale throughput and storage across any number of Azure regions worldwide. Here are some of the tools that are available to make you more productive with CosmosDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Cosmos DB Data Migrator
&lt;/h2&gt;

&lt;p&gt;Using the Cosmos DB data migrator, you can import from JSON files, CSV files, SQL, MongoDB, Azure Table storage, Amazon DynamoDB, and even Azure Cosmos DB SQL API collections into a new Cosmos DB instance. The data migrator is open-source and &lt;a href="https://github.com/Azure/azure-documentdb-datamigrationtool" rel="noopener noreferrer"&gt;available here&lt;/a&gt;. You can build it from source or head over to the releases section to download the tool.&lt;/p&gt;

&lt;p&gt;You specify where you want to import the data from&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-data-migrator-import.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-data-migrator-import.png" alt="Cosmos DB Data Migrator Import"&gt;&lt;/a&gt;&lt;br&gt;
      Cosmos DB Data Migrator Import&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;/figcaption&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You then specify how you want to export the data and more importantly the connection type which is under advanced options. You can read about the different connection policies from the &lt;a href="https://docs.microsoft.com/bs-latn-ba/azure/cosmos-db/performance-tips" rel="noopener noreferrer"&gt;Cosmos DB Docs&lt;/a&gt;. If you are behind a corporate firewall, Gateway mode is your best bet. Hit next and wait for the data migration to finish.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-data-migrator-export.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-data-migrator-export.png" alt="Cosmos DB Data Migrator Export"&gt;&lt;/a&gt;&lt;br&gt;
      Cosmos DB Data Migrator Export&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;/figcaption&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can automate these steps via the command-line as well. Head over to the folder where the tool was extracted, open the command line and run &lt;code&gt;dt.exe --help&lt;/code&gt;. This launch the console version of the tool with useful help on usage and options on how to invoke the migrator via the command line. Great for automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Cosmic Clone
&lt;/h2&gt;

&lt;p&gt;Cosmic Clone helps in creation of a backup copy of your Cosmos Collection in few clicks and provides options to perform first of its kind data masking and anonymization tasks on Azure Cosmos DB. This one is open-source as well and you can &lt;a href="https://github.com/microsoft/CosmicClone" rel="noopener noreferrer"&gt;check this out on GitHub&lt;/a&gt;. The stand-out features of cosmic clone is the ability to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create collections with similar settings(indexes, partition, TTL etc) on target instances&lt;/li&gt;
&lt;li&gt;Anonymize data through scrubbing or shuffling of sensitive data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You choose the source Cosmos DB instance and the target instance, specify what you want to clone and add data handling rules and then wait for the cloning process to complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmic-clone3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmic-clone3.png" alt="Cosmic Clone Data Handling Rules"&gt;&lt;/a&gt;&lt;br&gt;
      Cosmic Clone Handling Rules&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;/figcaption&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There is no command-line options to automate this process and more importantly the &lt;a href="https://github.com/microsoft/CosmicClone/blob/master/CosmosClone/CosmosCloneCommon/Utility/CosmosDBHelper.cs#L23" rel="noopener noreferrer"&gt;connection policy is set to TCP&lt;/a&gt; which does not play well with corporate firewalls. So, if you are behind a firewall, clone the repo, modify the policy, build and run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Cosmos Capacity Calculator
&lt;/h2&gt;

&lt;p&gt;This should have been called cost calculator and not capacity calculator. Anyway, you can check out the calculator &lt;a href="https://cosmos.azure.com/capacitycalculator/" rel="noopener noreferrer"&gt;at this website&lt;/a&gt;. The estimate takes into account a lot of different factors when calculating the final cost.&lt;/p&gt;

&lt;p&gt;When you sign-in with your email account after &lt;strong&gt;ignoring the unverified warning on the sign-in page&lt;/strong&gt; , more form fields are available and you can specify more details about your workload to get better, more accurate estimates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-count-advanced.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-count-advanced.png" alt="Cosmos DB Cost Calculator"&gt;&lt;/a&gt;&lt;br&gt;
      Cosmos DB Cost Calculator&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;/figcaption&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;Save Estimate&lt;/strong&gt; button just downloads a csv file. I don’t understand why the save estimate button and the ability to specify advanced information is available only when you sign-in. Seriously, What am I missing here ? Otherwise, the cost calculator is a useful tool to estimate costs up-front.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Cosmos DB Explorer
&lt;/h2&gt;

&lt;p&gt;I like the Azure Storage Explorer. I can browse the contents of your Azure Storage Accounts, Disks and Cosmos DB instances. But for some reason, I couldn’t get it to play nice with proxy settings at work. It would always fail with a 403 error. I was able to access my storage accounts without any issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-storage-explorer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2Fcosmos-tools%2Fcosmos-storage-explorer.png" alt="Cosmos DB Errors with Storage Explorer"&gt;&lt;/a&gt;&lt;br&gt;
      Cosmos DB errors with Storage Explorer&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;/figcaption&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I googled around like any good developer and found &lt;a href="https://www.bruttin.com/CosmosDbExplorer/" rel="noopener noreferrer"&gt;Cosmos Db Explorer&lt;/a&gt;. You can head to the &lt;a href="https://github.com/sachabruttin/CosmosDbExplorer/releases" rel="noopener noreferrer"&gt;releases section of their github repo&lt;/a&gt; and download the latest version or you can &lt;code&gt;choco install cosmosdbexplorer&lt;/code&gt; if you have chocolatey installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Visual Studio Code Extension for Cosmos DB
&lt;/h2&gt;

&lt;p&gt;Nothing beats not having to leave your IDE. The &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb" rel="noopener noreferrer"&gt;VS Code Extension for Cosmos DB&lt;/a&gt; enables you to do just that. The extension features a Cosmos DB Explorer to CRUD documents, collections, databases. There is support for Mongo Scrapbooks which allows you to run mongo commands with rich intellisense. Haven’t tried the scrapbooks yet.&lt;/p&gt;

&lt;p&gt;These are my favourite Cosmos DB tools. With these tools, I can explore my data, migrate data, back-up and anonymize the contents of my databases and calculate the estimated cost of running a Cosmos DB instance on Azure.&lt;/p&gt;

</description>
      <category>azurecosmosdb</category>
    </item>
    <item>
      <title>HanselMinutes-Plus-Plus : How I built a podcast transcription service on Azure in a week</title>
      <dc:creator>Gurucharan Subramani</dc:creator>
      <pubDate>Tue, 04 Jun 2019 00:00:00 +0000</pubDate>
      <link>https://forem.com/gurucharan94/hanselminutes-plus-plus-how-i-built-a-podcast-transcription-service-on-azure-in-a-week-8mb</link>
      <guid>https://forem.com/gurucharan94/hanselminutes-plus-plus-how-i-built-a-podcast-transcription-service-on-azure-in-a-week-8mb</guid>
      <description>&lt;p&gt;This is the story of how I wanted to try out the speech to text offerings from &lt;a href="https://azure.microsoft.com/en-in/services/cognitive-services/speech-services/"&gt;Azure Cognitive Services&lt;/a&gt; and eventually ended up building a prototype of a podcast transcription service that &lt;strong&gt;automatically transcribes any new episode of your podcast and displays synchronized transcripts alongside your audio making your podcast more accessible.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Transcripts provide multiple benefits for the podcast host as well as the listeners. More importantly, it is the right thing do because it makes your web content more accessible. You can read more about this at &lt;a href="https://podcast-accessibility.com/"&gt;Podcast Accessibility&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to see this in action, take a look at &lt;strong&gt;&lt;a href="https://hanselminutesplusplus.azurewebsites.net"&gt;Hanselminutes++&lt;/a&gt;&lt;/strong&gt; (running on free plan on Azure) which is a minimal clone of the popular &lt;a href="https://www.hanselminutes.com/"&gt;Hanselminutes podcast&lt;/a&gt; with synchronized transcripts. &lt;/p&gt;

&lt;p&gt;You can also find the source code &lt;a href="https://github.com/GuruCharan94/az-podcast-transcriber"&gt;on github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The transcripts for HanselMinutes are Artificial Intelligence powered and is about 85%-90% accurate (rough calculation) and extremely affordable at approximately 1 USD / hour of audio when done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Story Time
&lt;/h2&gt;

&lt;p&gt;The meeting / conversation transcription showcase from Microsoft Build 2019 was lingering on the back of my head and so I wanted to try it out. Although, the meeting transcription service required custom devices, I liked what I saw with Batch Transcription offerings. I decided to give that a try and this is what followed.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Azure Batch Transcription
&lt;/h3&gt;

&lt;p&gt;I followed the &lt;a href="https://docs.microsoft.com/en-in/azure/cognitive-services/speech-service/batch-transcription"&gt;docs&lt;/a&gt; and created a new Speech Services instances on &lt;strong&gt;Standard S0&lt;/strong&gt; plan in the West US region. I decided to start making POST requests to the transcription endpoint from the &lt;a href="https://westus.cris.ai/swagger/ui/index"&gt;Swagger Page&lt;/a&gt; after authorizing the requests with my subscription key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "recordingsUrl": "&amp;lt;SAS URI of Blob&amp;gt;",
  "models": [],
  "locale": "en-US",
  "name": "Title of the episode",
  "description": "An optional description of the episode",
  "properties": {
    "ProfanityFilterMode": "Masked",
    "PunctuationMode": "DictatedAndAutomatic"
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I realized that I had to input valid Azure Blob SAS URI for the &lt;code&gt;recordingsUrl&lt;/code&gt; field. So, I downloaded a mp3 file from Hanselminutes, uploaded them to storage account with storage explorer, generated SAS URI and made requests.&lt;/p&gt;

&lt;p&gt;Every episode of Hanselminutes is 30 minutes long and it took almost the same time to transcribe each episode. I learnt that I can register a &lt;a href="https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/webhooks"&gt;webhook&lt;/a&gt; where the results will be POSTed once they are completed and avoid constantly polling the API to check if transcription is completed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side Comment:&lt;/strong&gt; I tried transcribing all the Hanselminutes episodes from 2018 and 2019 but there were issues transcribing certain episodes and &lt;a href="https://stackoverflow.com/questions/56329927/azure-cognitive-services-batch-transcription-api-responds-with-error-message"&gt;I have a question on StackOverflow about it.&lt;/a&gt; I also have questions about request throttling and support for blob storage that are not clear for me from the docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Azure Functions
&lt;/h3&gt;

&lt;p&gt;I got my first transcription result and I was happy with what I saw. Now, I wanted to transcribe several episodes and realized that it quickly became a tedious task to download mp3 files, upload to Azure Storage and then fire off transcription requests. My developer brain was screaming out for something like &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/"&gt;Azure Functions&lt;/a&gt; and so it I wrote some.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.1 Http Triggered Function
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Accepts a URL of an mp3 file in the triggering request&lt;/li&gt;
&lt;li&gt;Downloads the mp3 file as a stream.&lt;/li&gt;
&lt;li&gt;Uploads it to a Storage Account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.2 Azure Blob Triggered Function
&lt;/h4&gt;

&lt;p&gt;This function is triggered whenever there is a new blob with an &lt;em&gt;.mp3&lt;/em&gt; extension in the storage account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates SAS URI for the blob&lt;/li&gt;
&lt;li&gt;Makes a transcription request to the transcription endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.3 HTTP Triggered Azure Function
&lt;/h4&gt;

&lt;p&gt;This is the function that receives the HTTP callbacks when the transcription process is completed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processes the transcription results.&lt;/li&gt;
&lt;li&gt;Initially I wanted to simply view the transcripts&lt;/li&gt;
&lt;li&gt;Later (when I started to build a Hanselminutes clone) decided to store them inside Azure CosmosDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Azure Logic App
&lt;/h3&gt;

&lt;p&gt;I still needed links to the audio file for each episode of the podcast. I know I can get that from the RSS Feed and I decided to opt for a no-code solution and use the &lt;a href="https://docs.microsoft.com/en-us/azure/connectors/connectors-create-api-rss"&gt;RSS Connector&lt;/a&gt; to parse RSS feeds. Although I say things like no-code solution, the truth is that I wanted to try out Logic Apps. ;) ;)&lt;/p&gt;

&lt;h4&gt;
  
  
  3.1 A Custom RSS Feed
&lt;/h4&gt;

&lt;p&gt;Hanselminutes is a weekly podcast but I needed a RSS Feed that updates way more frequently and on my schedule. I decided to set up my own RSS Feed with my fork of the &lt;a href="http://lorem-rss.herokuapp.com/"&gt;Lorem RSS Feed&lt;/a&gt; where I have only feed item that regularly updates.&lt;/p&gt;

&lt;p&gt;For development purposes, I trigger a check on my fake RSS Feed for updates and when there are updates to my feed, HTTP POST items from Hanselminutes feed to the HTTP triggered azure function. Not pretty, but works for now.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Azure Web App and CosmosDB
&lt;/h3&gt;

&lt;p&gt;I searched the internet to see if Hanselminutes already had transcriptions and I only found some broken / outdated links. I’m guessing transcripts existed at one point but they no longer do. This was a good excuse for me to build a minimal Hanselminutes clone with transcriptions. I decided to go with &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction"&gt;CosmosDB&lt;/a&gt; to store transcripts and updated the Azure Function to store results in CosmosDB and built an ASP NET Core Web App that spoke to CosmosDB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDaz7mmr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/hanselminutes-clone/v1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDaz7mmr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/hanselminutes-clone/v1.jpg" alt="High level overview of the initial version"&gt;&lt;/a&gt; High Level Overview of the Initial Version&lt;/p&gt;

&lt;h2&gt;
  
  
  Costs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The core transcription service from &lt;a href="https://azure.microsoft.com/en-in/pricing/details/cognitive-services/speech-services/"&gt;Azure Cognitive Services&lt;/a&gt; costs &lt;strong&gt;1 USD / hour&lt;/strong&gt; of audio in the Standard Plan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://azure.microsoft.com/en-in/pricing/details/storage/blobs/"&gt;Azure Storage&lt;/a&gt;, &lt;a href="https://azure.microsoft.com/en-in/pricing/details/functions/"&gt;Azure Functions&lt;/a&gt; and &lt;a href="https://azure.microsoft.com/en-in/pricing/details/logic-apps/"&gt;Logic Apps&lt;/a&gt; are relatively dirt cheap that you can consider them as free value additions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I store the transcripts on &lt;a href="https://azure.microsoft.com/en-in/pricing/details/cosmos-db/"&gt;Azure Cosmos DB&lt;/a&gt; which has a complex pricing model and it costs a fair bit with the starting price around &lt;strong&gt;24 USD / month.&lt;/strong&gt; Continue reading to know how the next version addresses this in the next version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Hanselminutes clone is hosted on Azure App Service but if you host a podcast you would already have your own website.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Plans for the Next Version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Clearly, Azure CosmosDB is a major cost barrier and the costs can quickly skyrocket with the popularity of the podcasts. I am considering &lt;a href="http://www.levibotelho.com/development/commit-a-file-with-the-github-api/"&gt;posting transcription results directly to github&lt;/a&gt; instead of storing it inside CosmosDB. This allows the transcripts to be “open source” and take community contributions towards increasing accuracy and more importantly drive the costs down significantly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The RSS Connector on Logic App was great for a quick start but it has introduced a lot of limitations and ‘code smells’. I have decide to replace the RSS connector with &lt;a href="https://github.com/codehollow/FeedReader/"&gt;this library&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I plan to provide two separate Azure Functions, one to transcribe new episodes and the other to transcribe episodes from your archive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The editing experience could also be much better. In fact, it would be great to have a standalone editor running on github pages with the ability to import and edit speech to text results generated by Azure and later accommodate other transcription engines as well. &lt;strong&gt;Import your transcript ➡️ Make corrections ➡️ Export. Send a pull request.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The ability to distinguish between speakers would be great but “not today”…&lt;strong&gt;[Update 17 June,2019] : Azure Speech Services now supports &lt;a href="https://cognitive.uservoice.com/forums/555925-speaker-recognition-api/suggestions/34823824-add-support-for-speaker-diarization-for-untrained?tracking_code=d20ff299ba13b35ae06e9d299e59bf73"&gt;Speaker Diarization&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I expect the next version to shape up like the picture below and once the project reaches there, the transcription costs will be available at approx &lt;strong&gt;1 USD / hour&lt;/strong&gt; which is how much Azure Transcription Service cost. The rest of the value add stuff which complements your workflow is available at a paltry budget. No more of that submit your audio file for transcription and we will email you transcripts in 24 hours that you can later add to your website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YASsGy2z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/hanselminutes-clone/v2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YASsGy2z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gurucharan.in/assets/images/hanselminutes-clone/v2.jpg" alt="Pictorial overview of the next version"&gt;&lt;/a&gt;&lt;br&gt;
  High Level Overview of the Next Version&lt;br&gt;
  &lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Remarks
&lt;/h2&gt;

&lt;p&gt;It started with me wanting to try out the Batch transcription API on a Saturday morning to see if it was any good. A week’s worth of effort later, I end up here. Although this was a fun side-project, I am quite happy with how this turned out considering the below facts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Did I know anything about how the internals of speech-to-text Artificial Intelligence magic works ? No.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forget Artificial Intelligence. I did not know how to implement synchronized scroll by myself. I spent a good 4-6 hours on that before giving up and building on top of the &lt;a href="https://github.com/flesler/jquery.scrollTo"&gt;scrollTo Library&lt;/a&gt;. Was never good with JS anyway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The only “original code” that I wrote was the logic to to trigger the scroll of in sync with the audio. That was it. Around 50 lines of javascript. The rest of the code was mostly straight out from the Azure docs.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It has been a fun ride &lt;a href="https://www.hanselman.com/blog/WeAreAbstractingOnTheShouldersOfGiants.aspx"&gt;building on the shoulders of the giants and their abstractions&lt;/a&gt; and I want to see how far forward I can take this.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>a11y</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Improve Your Azure Security with the Secure DevOps Kit for Azure (AzSK)</title>
      <dc:creator>Gurucharan Subramani</dc:creator>
      <pubDate>Tue, 30 Apr 2019 00:00:00 +0000</pubDate>
      <link>https://forem.com/gurucharan94/how-to-improve-your-azure-security-with-the-secure-devops-kit-for-azure-azsk-3m16</link>
      <guid>https://forem.com/gurucharan94/how-to-improve-your-azure-security-with-the-secure-devops-kit-for-azure-azsk-3m16</guid>
      <description>&lt;p&gt;&lt;a href="https://azsk.azurewebsites.net/" rel="noopener noreferrer"&gt;The Secure DevOps Kit for Azure (AzSK)&lt;/a&gt; is a free and open source toolkit that checks your Azure resources for operational and security best practices. The kit in it’s core is a Powershell Module that caters to the end to end Azure subscription and resource security needs by checking key areas like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subscription Security&lt;/strong&gt; - ARM Policies, RBAC (Role Based Access Control), Security Center Configurations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Security&lt;/strong&gt; - Https Configurations, Firewall Rules, Key Rotation, Token Expiration, Backup and Disaster Recovery Configuration and many others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post helps you get started with the core features of the Secure DevOps Kit by showing you how to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install AzSK and running your first scan&lt;/li&gt;
&lt;li&gt;Understand the scan results.&lt;/li&gt;
&lt;li&gt;Push scan results to Azure Log Analytics and visualizing scan results like below screenshot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have further provided links to the official docs if you want to try out some of the advanced features such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customizing the security checks&lt;/li&gt;
&lt;li&gt;Azure DevOps (VSTS) and Jenkins integrations to include these checks in your deployment pipeline.&lt;/li&gt;
&lt;li&gt;Continuous security monitoring post deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FAzSK-LogAnalytics.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FAzSK-LogAnalytics.png" alt="AzSK-Log Analytics"&gt;&lt;/a&gt;AzSK-Log Analytics&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Installing AzSK and Running your First Scan&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I am assuming you, dear reader, have basic knowledge of Powershell. In case you need to get started or brush up on your Powershell, the AzSK team have done a fantastic job to help you with &lt;a href="https://azsk.azurewebsites.net/Blogs/Blog1.html" rel="noopener noreferrer"&gt;this crash course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ensure you have &lt;strong&gt;PowerShell version 5&lt;/strong&gt; or higher installed on your machine. You can check the version of Powershell installed on your machine by running &lt;code&gt;$PSVersionTable&lt;/code&gt; on your PowerShell window. Update your PowerShell version if you need to. The update is mostly straight-forward. Google is your best friend here 😊&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FPSVersion.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FPSVersion.png" alt="Powershell Version"&gt;&lt;/a&gt;Powershell Version&lt;/p&gt;

&lt;p&gt;Once you have the right version of Powershell installed the next step is that you &lt;strong&gt;trust me, copy and paste scripts&lt;/strong&gt; into your Powershell ISE Window and run them. 😊 The scripts use the new Azure Powershell (Az) Modules extensively. I have included an overview of what the script attempts to accomplish and also in-line comments wherever necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Copy and Paste - Drill 1&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Drill 1 involves the installation of The Secure DevOps Kit for Azure. The installation does not need admin privileges and installs the modules for the currently logged in user. The Azure Security Kit relies heavily on the new Azure Powershell (Az) Modules. You can run the below scripts to install AzSK on your machine. The installation might take some time and in the meanwhile, you can take a look at the &lt;a href="https://azsk.azurewebsites.net/00a-Setup/Readme.html" rel="noopener noreferrer"&gt;official setup instructions&lt;/a&gt; which contains answers to frequent installation problems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install AzSK
Install-Module AzSK -Scope CurrentUser -AllowClobber -Force

# Display some info about AzSK
Get-InstalledModule AzSK

# Lists all the commands available in AzSK
Get-Help AzSK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Copy and Paste - Drill 2&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that AzSK is installed successfully, drill 2 involves the below script which helps us to obtain the most value from AzSK by setting up a Log Analytics Workspace to visualize the results.&lt;/p&gt;

&lt;p&gt;The script below&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imports AzSK into the current session&lt;/li&gt;
&lt;li&gt;Prompts you to login to Azure&lt;/li&gt;
&lt;li&gt;Creates a new Resource Group in a subscription of your choice&lt;/li&gt;
&lt;li&gt;It then creates a Log Analytics workspace with the AzSK visualizations&lt;/li&gt;
&lt;li&gt;Configures AzSK to push the scan results to the newly created workspace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save the below script in a file called &lt;strong&gt;AzSK-setup.ps1&lt;/strong&gt;. From your Powershell ISE window which you already have open, you can run &lt;code&gt;.\AzSK-setup.ps1 -SubscriptionName "your-subscription-name"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Param
(
    [Parameter(Mandatory=$true)] [string]$SubscriptionName,
    [string]$Location = "East US"
)
$RgName = "AzSK-GettingStarted-RG"

#The script requires Powershell 5 or higher. Imports AzSK in current session.
Import-Module AzSK

Connect-AzAccount

Get-AzSubscription -SubscriptionName "Visual Studio Professional" | Set-AzContext

# Check if a resource group by name "AzSK-GettingStarted-RG" exists
Get-AzResourceGroup -Name $RgName `
                         -ErrorAction SilentlyContinue `
                         -ErrorVariable rgError

if ($rgError)
{ # Resource Group Does not exists. Create a new one.
   New-AzResourceGroup -Name $RgName -Location $Location
}

#Create a Log analytics Workspace if not exists
$LogAnalyticsWorkspace = Get-AzOperationalInsightsWorkspace `
                        -ResourceGroupName $RgName | Select -First 1

if ($LogAnalyticsWorkspace.Count -eq 0)
{
    $WorkspaceName = "AZSK-log-analytics-" + (Get-Random -Maximum 99999)
    $LogAnalyticsWorkspace = New-AzOperationalInsightsWorkspace `
                                -ResourceGroupName $RgName `
                                -Name $WorkspaceName `
                                -Location $Location `
                                -Sku "standalone"
}

#Get Subscription Id
$SubscriptionId = Get-AzSubscription `
                    | Where-Object Name -eq $SubscriptionName `
                    | Select-Object Id

# Setup AzSK View in Log Analytics
Install-AzSKOMSSolution -OMSSubscriptionId $SubscriptionId.Id `
                        -OMSResourceGroup $RgName `
                        -OMSWorkspaceId $LogAnalyticsWorkspace.CustomerId `
                        -DoNotOpenOutputFolder

$LogAnalyticsKeys = Get-AzOperationalInsightsWorkspaceSharedKeys `
                      -ResourceGroupName $RgName `
                      -Name $LogAnalyticsWorkspace.Name `

Set-AzSKOMSSettings -OMSWorkspaceID $LogAnalyticsWorkspace.CustomerId -OMSSharedKey $LogAnalyticsKeys.PrimarySharedKey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Copy and Paste - Drill 3&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is the fun part where we can finally scan our Azure Workloads and compare them against security best practices.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The below script scans a subscription of your choice and all the resources inside it. Running this script shows you the real time progress of the scan results on the console. &lt;strong&gt;The subscription scanned can be a different subscription to the one contains the Log Analytics Workspace.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The results are also summarized in CSV, PDF and Json formats in addition to pushing it to the Log Analytics workspace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The scan also generates fix scripts (doesn’t run them) which can be used to automatically fix failing security controls.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save the below script in a file called &lt;strong&gt;AzSK-Scan.ps1&lt;/strong&gt;. From your Powershell ISE window which you already have open, you can run &lt;code&gt;.\AzSK-Scan.ps1 -SubscriptionName "your-subscription-name"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Param
(
    [Parameter(Mandatory=$true)][string]$SubscriptionName
)
Import-Module AzSK
Connect-AzAccount # Skip this in cloud shell
# Run this in a new Powershell Window after running previous script

$SubscriptionId = Get-AzSubscription `
                    | Where-Object Name -eq $SubscriptionName `
                    | Select-Object Id

# Sets Location where scan results are stored to current folder.
Set-AzSKUserPreference -OutputFolderPath (Get-Location).Path

# Scan the subscription against Security Best Practices
Get-AzSKSubscriptionSecurityStatus -SubscriptionId $SubscriptionId.Id -GeneratePDF Portrait -GenerateFixScript

# Scan the individual resources against Security Best Practices
Get-AzSKAzureServicesSecurityStatus -SubscriptionId $SubscriptionId.Id -GeneratePDF Portrait -GenerateFixScript

# Resets location where scan results are stored.
Set-AzSKUserPreference -ResetOutputFolderPath
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;AzSK Scan Results&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The AzSK scan results are stored inside a folder called AzSKLogs relative to the current working directory. The .csv file is a good starting point to understand the results. They contain detailed information about the controls scanned, the status, the severity and other details that are self-explanatory. &lt;strong&gt;Convert this to a spread-sheet, format it as table, add your excel magic and email this to your boss.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The fix scripts are also generated thanks to the &lt;code&gt;GenerateFixScript&lt;/code&gt; argument. &lt;strong&gt;Proceed with caution and test the fix scripts before running it against production workloads.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can head over to the Azure Portal and navigate to the Log Analytics Workspace and see that the scan results are also pushed to the Log Analytics workspace that was configured. &lt;a href="https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-data-ingestion-time" rel="noopener noreferrer"&gt;It usually takes around 30 minutes on your first scan for the scan results to show up in Log Analytics&lt;/a&gt;. The subsequent results show up much faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip :&lt;/strong&gt; The built-in visualization of the log analytics &lt;strong&gt;shows only the baseline controls for the last 3 days&lt;/strong&gt;. Base line controls are the most important security controls that ensure a decent basic level of security.&lt;/p&gt;

&lt;p&gt;To match the results in the .csv file you have to edit the workspace and specifically modify the queries across every blade and specifically remove the &lt;strong&gt;&lt;code&gt;where TimeGenerated &amp;gt; ago(3d)&lt;/code&gt;&lt;/strong&gt; and the &lt;strong&gt;&lt;code&gt;IsBaselineControl_b == true&lt;/code&gt;&lt;/strong&gt; parts from the query. You can also add / remove / edit the blades to customize the AzSK Solution for Log Analytics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FEdit-AzSK-Queries.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FEdit-AzSK-Queries.png" alt="AzSK-Edit-Queries"&gt;&lt;/a&gt;AzSK-Edit-Queries&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Advanced Features&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html" rel="noopener noreferrer"&gt;Continuous Assurance (CA) Mode&lt;/a&gt;&lt;/strong&gt; - This is an Azure Automation runbook that scans your subscription at a scan frequency of your choosing. This greatly help situation where systems are already live and you want to monitor the security posture continuously to avoid &lt;em&gt;security drift&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html#continuous-assurance-ca---central-scan-mode" rel="noopener noreferrer"&gt;Continuous Assurance (CA) in Central Scan mode&lt;/a&gt;&lt;/strong&gt; - When you have a large number of subscriptions, you can setup &lt;strong&gt;CA in Central Scan mode&lt;/strong&gt; which provides you the ability to monitor several target subscriptions using a single master subscription that contains the automation runbook. Configuring this can take up a couple of hours and is flaky. &lt;a href="https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html" rel="noopener noreferrer"&gt;Carefully follow these instructions&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://azsk.azurewebsites.net/07-Customizing-AzSK-for-your-Org/Readme.html" rel="noopener noreferrer"&gt;Customizing the Security Rules&lt;/a&gt;&lt;/strong&gt; - AzSK also provides a possibility to customize the security controls which helps you to do things such as disable certain controls, change control severity, modify recommendation messages etc. based on your context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Alerting&lt;/strong&gt; - Since the scan results are configured to be sent to Azure Log Analytics workspace, you can configure alerts using the Log Analytics API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://azsk.azurewebsites.net/03-Security-In-CICD/Readme.html" rel="noopener noreferrer"&gt;CI/CD Integration with Azure DevOps and Jenkins&lt;/a&gt;&lt;/strong&gt; - Running these security scans periodically from a PS console is great but integrating them in your CI / CD pipeline is even better. AzSK provides extensions for Azure DevOps (formerly VSTS) and Jenkins.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FAZSK-AzureDevOps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gurucharan.in%2Fassets%2Fimages%2FAzSK%2FAZSK-AzureDevOps.png" alt="AzSK-AzureDevOps"&gt;&lt;/a&gt;AzSK-AzureDevOps&lt;/p&gt;

&lt;p&gt;With configurable security policies, auto generated fixes, multiple results formats, CI/CD extension and out of the box Log Analytics dashboards with querying and alerting capabilities, the Secure DevOps Kit for Azure is a must have tool for teams working with Azure to adopt a security first mindset and create secure workloads on Azure.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>security</category>
      <category>loganalytics</category>
      <category>powershell</category>
    </item>
  </channel>
</rss>
