{"id":28166,"date":"2023-01-25T14:00:58","date_gmt":"2023-01-25T13:00:58","guid":{"rendered":"https:\/\/device-insight.com\/?post_type=developers-blog&#038;p=28166"},"modified":"2024-01-03T13:12:55","modified_gmt":"2024-01-03T12:12:55","slug":"vetting-azure-managed-applications-through-ci-cd","status":"publish","type":"developers-blog","link":"https:\/\/device-insight.com\/en\/developers-blog\/vetting-azure-managed-applications-through-ci-cd\/","title":{"rendered":"Vetting Azure Managed Applications through CI\/CD"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"28166\" class=\"elementor elementor-28166\" data-elementor-settings=\"{&quot;ha_cmc_init_switcher&quot;:&quot;no&quot;}\" data-elementor-post-type=\"developers-blog\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7b4f828b devel_blog_title elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7b4f828b\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1786bf7e blog_col\" data-id=\"1786bf7e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-fa4243a elementor-align-left devel_blog_back_btn ha-has-bg-overlay elementor-widget elementor-widget-button\" data-id=\"fa4243a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-size-sm\" role=\"button\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t<span class=\"elementor-button-icon\">\n\t\t\t\t<i aria-hidden=\"true\" class=\"hm hm-arrow-left1\"><\/i>\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Back<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-612acb44 elementor-widget elementor-widget-theme-post-title elementor-page-title elementor-widget-heading\" data-id=\"612acb44\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"theme-post-title.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">Vetting Azure Managed Applications through CI\/CD<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-539cc96 elementor-widget elementor-widget-post-info\" data-id=\"539cc96\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"post-info.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul class=\"elementor-inline-items elementor-icon-list-items elementor-post-info\">\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-6345c40 elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-custom\">\n\t\t\t\t\t\t\t\t\t\tStefan Hudelmaier\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-7f3e269 elementor-inline-item\">\n\t\t\t\t\t\t<a href=\"https:\/\/www.linkedin.com\/in\/stefan-hudelmaier\/\" target=\"_blank\" rel=\"noopener\">\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t\t<i aria-hidden=\"true\" class=\"fab fa-linkedin\"><\/i>\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-custom\">\n\t\t\t\t\t\t\t\t\t\thttps:\/\/www.linkedin.com\/in\/stefan-hudelmaier\/\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t<\/li>\n\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-b86a0c7 elementor-inline-item\" itemprop=\"datePublished\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-date\">\n\t\t\t\t\t\t\t\t\t\t<time>2023\/01\/25<\/time>\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-808e92e elementor-inline-item\" itemprop=\"about\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-terms\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-post-info__terms-list\">\n\t\t\t\t<a href=\"https:\/\/device-insight.com\/en\/developers_blog_category\/azure\/\" class=\"elementor-post-info__terms-list-item\">Azure<\/a>\t\t\t\t<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-17c17f87 elementor-widget elementor-widget-text-editor\" data-id=\"17c17f87\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The Azure Marketplace can be used to publish so-called Managed Applications and offer them to customers. Like with Google Play or the Apple App-Store, these Managed Application undergo a review process before they are made available. When we went through this process with <a href=\"https:\/\/device-insight.com\/ux4iot\/\" rel=\"noopener\">ux4iot<\/a>, we picked up some best practices, one of which we want to share in this blog post.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-de1fb1a elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"de1fb1a\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-44e83259 blog_col\" data-id=\"44e83259\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1377b04 elementor-widget elementor-widget-text-editor\" data-id=\"1377b04\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>There are two destinations for publishing\u00a0<a class=\"ad iq\" style=\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\" href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-resource-manager\/managed-applications\/overview\" target=\"_blank\" rel=\"noopener ugc nofollow\">Azure Managed Applications<\/a>. The first option is to make them available in the so-called Service Catalog. This means that they will only be available inside of your organization. This is useful for bundling functionality for internal purposes.<\/p><p>If you want to commercialize your application, however, you have to publish it to the Azure Marketplace, where it can be found and used by people outside of your own org. You submit the application via the\u00a0<a class=\"ad iq\" style=\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\" href=\"https:\/\/partner.microsoft.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Microsoft Partner Center<\/a>\u00a0and thereby kick off a validation process, where Microsoft staff is checking formal aspects of your submission (e.g. if your privacy policy is acceptable) as well as technical criteria. For the latter, the ARM template (<em class=\"ir\" style=\"box-sizing: inherit;\">mainTemplate.json<\/em>) that is at the heart of the Managed Application is evaluated, as well as other relevant files (e.g.\u00a0<em class=\"ir\" style=\"box-sizing: inherit;\">createUiDefinition.json<\/em>\u00a0which defines the workflow for creating new instances of your app).<\/p><p>Since the validation process is partly manual, it can take a couple of days. When technical issues are found, you are given feedback and potentially asked to correct any shortcomings. In order to speed things up and prevent time-consuming back and forth between yourself and the reviewers, you should perform the validity checks yourself\u00a0<span class=\"hu gw\" style=\"box-sizing: inherit; font-weight: bold;\">before<\/span>\u00a0submitting your app. Luckily, the tools that are used by the Microsoft staff for vetting the applications are available, in the form of the\u00a0<a class=\"ad iq\" style=\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\" href=\"https:\/\/github.com\/Azure\/arm-ttk\" target=\"_blank\" rel=\"noopener ugc nofollow\">Azure Resource Manager Template Toolkit (arm-ttk)<\/a>.<\/p><p>It makes sense to integrate arm-ttk in the CI\/CD process of your Managed App, so that the checks are automatically performed for every new version of your app.<\/p><p>In order to facilitate this process, we at\u00a0Device Insight\u00a0have created a Docker image that holds arm-ttk. You can find the repo containing the build\u00a0<a class=\"ad iq\" style=\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\" href=\"https:\/\/github.com\/deviceinsight\/arm-template-test-toolkit-docker\" target=\"_blank\" rel=\"noopener ugc nofollow\">on GitHub<\/a>. The resulting Docker image can be retrieved from the GitHub container registry.<\/p><p>Usage is quite simple:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-54965b0 elementor-widget elementor-widget-ha-source-code happy-addon ha-source-code happy-addon-pro\" data-id=\"54965b0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"ha-source-code.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"ha-source-code prism\" data-lng-type=\"markup\" data-after-copy=\"Copied\">\n\t\t\t<pre>\n\t\t\t\t\t\t\t<button class=\"ha-copy-code-button\">Copy to clipboard<\/button>\n\t\t\t\t\t\t\t<code class=\"language-markup\">\n\t\t\t\t\tTEMPLATE_DIR=$(mktemp -d)\ncp mainTemplate.json createUiDefinition.json $TEMPLATE_DIR\ndocker run \\\n    --rm -ti \\\n    -v $TEMPLATE_DIR:\/template \\\n    ghcr.io\/deviceinsight\/arm-template-test-toolkit-docker:main\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4433d3a elementor-widget elementor-widget-text-editor\" data-id=\"4433d3a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This checks your\u00a0<em class=\"ir\" style=\"box-sizing: inherit;\">mainTemplate.json<\/em>\u00a0and\u00a0<em class=\"ir\" style=\"box-sizing: inherit;\">createUiDefinition.json<\/em>\u00a0and outputs its findings. If there are problems the execution of the Docker container will fail with a non-zero exit code, conveniently also failing your CI\/CD job. If no problems are found, the exit code will be zero and the CI\/CD job will be successful.<\/p><p>The reason why a temporary directory is used in the example instead of mounting the directory holding the\u00a0<em class=\"ir\" style=\"box-sizing: inherit;\">mainTemplate.json<\/em>\u00a0and other files directly is that arm-ttk will check all files with a json extension. There might be other json files alongside\u00a0<em class=\"ir\" style=\"box-sizing: inherit;\">mainTemplate.json<\/em>\u00a0which contain content unknown to arm-ttk, causing it to fail.<\/p><p>Here is some example output:<\/p><p><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/max\/700\/1*Ntx6YSmHDvGRhWff6XvMxw.png\" \/><\/p><p><span style=\"letter-spacing: -0.06px;\">If you fix all findings that arm-ttk reports, it should be smooth sailing getting your Managed Application approved for publication in the Azure Marketplace.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e4cfeb7 blog_col elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"e4cfeb7\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-16d18dc\" data-id=\"16d18dc\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e1d2107 devel_blog_footer elementor-widget elementor-widget-post-info\" data-id=\"e1d2107\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"post-info.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul class=\"elementor-inline-items elementor-icon-list-items elementor-post-info\">\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-6345c40 elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-custom\">\n\t\t\t\t\t\t\t\t\t\tStefan Hudelmaier\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-7f3e269 elementor-inline-item\">\n\t\t\t\t\t\t<a href=\"https:\/\/www.linkedin.com\/in\/stefan-hudelmaier\/\" target=\"_blank\" rel=\"noopener\">\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t\t<i aria-hidden=\"true\" class=\"fab fa-linkedin\"><\/i>\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-custom\">\n\t\t\t\t\t\t\t\t\t\thttps:\/\/www.linkedin.com\/in\/stefan-hudelmaier\/\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t<\/li>\n\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7917c55c elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7917c55c\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t\t<div class=\"elementor-background-overlay\"><\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-78099873 blog_col\" data-id=\"78099873\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-753c7837 elementor-widget elementor-widget-heading\" data-id=\"753c7837\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Recommended posts<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-dc8065b elementor-widget elementor-widget-shortcode\" data-id=\"dc8065b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><div class=\"teasers teasers-single-post\"><div class=\"teasers__container\"><div class=\"teasers__single-teaser teasers__single-teaser--developer\"><div class=\"teasers__content\"><div class=\"date__box\"><div class=\"date__box-name date__box-name--developers\">Stefan Hudelmaier<\/div><div class=\"date__box-date date__box-date--developers\">2023\/01\/03<\/div><div><a href=\"https:\/\/device-insight.com\/en\/developers_blog_category\/azure\/\" class=\"date__box-button date__box-button--developers\">Azure<\/a><\/div><\/div><h2 class=\"headline\"><a href=\"https:\/\/device-insight.com\/en\/developers-blog\/azure-managed-applications-and-tags\/\">Managed Applications and tags<\/a><\/h2><div class=\"description\">How to set tags of a managed resource group when deploying Azure Managed Applications.<\/div><\/div><\/div><div class=\"teasers__single-teaser teasers__single-teaser--developer\"><div class=\"teasers__content\"><div class=\"date__box\"><div class=\"date__box-name date__box-name--developers\">Robert Lohr<\/div><div class=\"date__box-date date__box-date--developers\">2022\/11\/28<\/div><div><a href=\"https:\/\/device-insight.com\/en\/developers_blog_category\/azure\/\" class=\"date__box-button date__box-button--developers\">Azure<\/a><\/div><\/div><h2 class=\"headline\"><a href=\"https:\/\/device-insight.com\/en\/developers-blog\/use-azure-ad-workload-identity-for-pod-assigned-managed-identity-in-aks\/\">Use Azure AD Workload Identity for Pod-Assigned Managed Identity in AKS<\/a><\/h2><div class=\"description\">How to make your life easier using Azure AD Workload Identity for authentication within AKS.<\/div><\/div><\/div><\/div><\/div>\r\n\n<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>How to speed up reviews for Azure Managed Applications with the right validity checks.<\/p>\n","protected":false},"author":13,"featured_media":0,"menu_order":0,"template":"elementor_header_footer","meta":{"_acf_changed":false},"tags":[141],"developers_blog_category":[138],"class_list":["post-28166","developers-blog","type-developers-blog","status-publish","hentry","tag-azure","developers_blog_category-azure"],"acf":[],"_links":{"self":[{"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/developers-blog\/28166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/developers-blog"}],"about":[{"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/types\/developers-blog"}],"author":[{"embeddable":true,"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/users\/13"}],"version-history":[{"count":20,"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/developers-blog\/28166\/revisions"}],"predecessor-version":[{"id":32408,"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/developers-blog\/28166\/revisions\/32408"}],"wp:attachment":[{"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/media?parent=28166"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/tags?post=28166"},{"taxonomy":"developers_blog_category","embeddable":true,"href":"https:\/\/device-insight.com\/en\/wp-json\/wp\/v2\/developers_blog_category?post=28166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}