<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PowerShell &#8211; JoseLCAguilar</title>
	<atom:link href="https://www.joselcaguilar.com/category/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.joselcaguilar.com</link>
	<description></description>
	<lastBuildDate>Sun, 14 Apr 2019 23:44:31 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.8</generator>

<image>
	<url>https://www.joselcaguilar.com/wp-content/uploads/2018/02/Favicon_64x64.png</url>
	<title>PowerShell &#8211; JoseLCAguilar</title>
	<link>https://www.joselcaguilar.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Azure Functions &#038; MSI vs. Key Vault Rest API</title>
		<link>https://www.joselcaguilar.com/2018/06/azure-functions-msi-vs-key-vault-rest-api/</link>
					<comments>https://www.joselcaguilar.com/2018/06/azure-functions-msi-vs-key-vault-rest-api/#respond</comments>
		
		<dc:creator><![CDATA[JoseLCAguilar]]></dc:creator>
		<pubDate>Mon, 25 Jun 2018 17:29:35 +0000</pubDate>
				<category><![CDATA[Azure Functions]]></category>
		<category><![CDATA[Key Vaults]]></category>
		<category><![CDATA[MSI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure PowerShell]]></category>
		<category><![CDATA[AzureRM]]></category>
		<guid isPermaLink="false">https://www.joselcaguilar.com/?p=232</guid>

					<description><![CDATA[Buenas tardes a tod@s, En [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="color: #000000;">Buenas tardes a tod@s,</span></p>
<p><span style="color: #000000;">En otra entrega más por este fabuloso y cambiante mundo del <strong>Cloud Computing</strong>, me gustaría presentaros un reto, el cual, en el momento que estoy escribiendo esta entrada <strong>2</strong> de los <strong>servicios</strong> que voy a enseñar se encuentran en modo <strong>Preview</strong>, pero&#8230; ¿quién dice que la proactividad e investigación no deba estar por delante para recomendar lo mejor a tus clientes, y más, cuando tratamos temas de <strong>seguridad</strong>?</span></p>
<p><span style="color: #000000;">¿Cuántas veces no hemos escrito <strong>credenciales hardcodeadas</strong> en un <strong>script/app</strong> al picar el código y se nos ha quedado ahí al compartirlo o simplemente al llevarlo a producción?</span></p>
<p><span style="color: #000000;">Por suerte a la hora de compartir, tenemos gracias a <strong>GIT</strong> un archivo brillante denominado <a href="https://git-scm.com/docs/gitignore">.gitignore</a> en el cual podemos almacenar nuestras credenciales y no se sincronizarán, pero, ¿y si quisiéramos dejar corriendo una <strong>aplicación</strong> o <strong>script</strong> en modo <strong>serverless</strong>? ¿y si me comprometen el acceso a la <strong>webapp</strong> o símplemente me consiguen impersonar el usuario?</span></p>
<p><span style="color: #000000;">Ya es hora de cambiar eso, así que, en esta entrada, vamos a mostrar la posibilidad de olvidarnos de credenciales en <strong>Azure Functions</strong> gracias a <strong>Management Service Identity</strong> y <strong>Key Vaults</strong>.</span></p>
<p><span style="color: #000000;">Para aquel o aquella que no sepa de qué hablo, pongo un poco en contexto:</span></p>
<ul>
<li><strong>Azure Functions:</strong> Nos permite <strong>ejecutar código a petición</strong> sin necesidad de aprovisionar ni administrar explícitamente la infraestructura, ese código puede ser ejecutado mediante llamadas webhook, scheduler, etc.</li>
</ul>
<p style="padding-left: 60px;"><span style="color: #000000;">Más info: </span><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview">https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview</a></p>
<ul>
<li><strong>Managed Service Identity:</strong> Proporciona a los servicios de Azure una <strong>identidad administrada</strong> automáticamente en <strong>Azure Active Directory</strong>.</li>
</ul>
<p style="padding-left: 60px;"><span style="color: #000000;">Más info y servicios disponibles actualmente:</span> <a href="https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/services-support-msi">https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/services-support-msi</a></p>
<ul>
<li><strong>Key Vaults: </strong>Ayuda a proteger claves criptográficas y secretos usados por servicios y aplicaciones en la nube a través del uso de claves que están protegidas por <strong>módulos de seguridad de hardware (HSM)</strong>.</li>
</ul>
<p style="padding-left: 60px;"><span style="color: #000000;">Más info:</span> <a href="https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis">https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis</a></p>
<p><span style="color: #000000;">Ahora que nos hemos puesto un poco en contexto, comentar que los dos servicios en <strong>Preview</strong> actualmente son: <strong>Azure Functions</strong> haciendo uso de <strong>PowerShell</strong> y <strong>MSI</strong> (Managed Service Identity).</span></p>
<p><span style="color: #000000;">Pues bien, es hora de ponernos manos a la obra, mediante los siguientes pasos:</span></p>
<ul>
<li>Creamos nuestra aplicación de identidad administrada habilitando <strong>Managed Service Identity</strong> en nuestra función, dentro del mismo blade de <strong>Azure Functions</strong>:</li>
</ul>
<p><img fetchpriority="high" decoding="async" class="aligncenter size-large wp-image-233" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-1024x399.png" alt="" width="640" height="249" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-1024x399.png 1024w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-300x117.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-768x299.png 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-500x195.png 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-950x370.png 950w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1-900x351.png 900w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions1.png 1050w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p><img decoding="async" class="aligncenter wp-image-256" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions2.jpg" alt="" width="374" height="128" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions2.jpg 739w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions2-300x103.jpg 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AzureFunctions2-500x171.jpg 500w" sizes="(max-width: 374px) 100vw, 374px" /></p>
<ul>
<li>Una vez creada, procedemos a <strong>dar permisos</strong> a nuestra aplicación administrada sobre las <strong>políticas de acceso</strong> de nuestro <strong>Key Vault</strong> para poder así obtener los secretos:</li>
</ul>
<p><img decoding="async" class="aligncenter size-large wp-image-235" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-1024x430.png" alt="" width="640" height="269" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-1024x430.png 1024w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-300x126.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-768x323.png 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-500x210.png 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-1166x490.png 1166w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-881x370.png 881w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies-900x378.png 900w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultAccessPolicies.png 1514w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<ul>
<li>Imaginemos que hemos insertado <strong>2 Secrets</strong> manualmente, por ejemplo, <strong>appId</strong> y <strong>appKey</strong> para que otro <strong>SPN</strong> realice la autenticación con Azure en nuestra aplicación, a continuación mostraremos el caso de <strong>appId</strong>:</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-236 " src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultSecrets.png" alt="" width="448" height="211" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultSecrets.png 847w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultSecrets-300x141.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultSecrets-768x362.png 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultSecrets-500x236.png 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/KeyVaultSecrets-785x370.png 785w" sizes="auto, (max-width: 448px) 100vw, 448px" /></p>
<ul>
<li>En este último punto, veremos cómo se realizaría la parte del código en <strong>PowerShell</strong>, pero de igual manera, al tratarse de un <strong>GET</strong> a la <strong>REST API</strong> de <strong>Azure</strong> podemos realizar de manera similar la llamada para obtener nuestro secreto deseado con <strong>cualquier lenguaje</strong> que soporte <strong>Azure Functions</strong>:</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">$vaultName = "z0"
$vaultSecretName = "appId"

$tokenAuthURI = $Env:MSI_ENDPOINT + "?resource=https://vault.azure.net&amp;api-version=2017-09-01"
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"Secret"="$env:MSI_SECRET"} -Uri $tokenAuthURI
$accessToken = $tokenResponse.access_token
Write-Output $accessToken

$headers = @{ 'Authorization' = "Bearer $accessToken" }
$queryUrl = "https://$vaultName.vault.azure.net/secrets/" +$vaultSecretName + "?api-version=2016-10-01"

$keyResponse = Invoke-RestMethod -Method GET -Uri $queryUrl -Headers $headers

Write-Output $KeyResponse.value</code></pre>
<p><span style="color: #000000;">Si nos fijamos en el código, estamos solicitando nuestro token a un audience diferente (<a href="https://vault.azure.net">https://vault.azure.net</a>), nos ocurre algo parecido a la </span><a href="https://www.joselcaguilar.com/2018/06/autenticacion-azure-sql-service-principal-en-powershell/">entrada anterior</a><span style="color: #000000;">, debemos de tenerlo en cuenta para no llamar al audience por defecto.</span></p>
<p><span style="color: #000000;">Si decodificamos nuestro token con la herramienta proporcionada por <a href="https://jwt.io/">jwt.io</a> podemos ver que la estructura es correcta:</span></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-238" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-1024x410.png" alt="" width="640" height="256" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-1024x410.png 1024w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-300x120.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-768x307.png 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-500x200.png 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-1225x490.png 1225w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-925x370.png 925w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault-900x360.png 900w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/JWTAudienceKeyVault.png 1705w" sizes="auto, (max-width: 640px) 100vw, 640px" /></p>
<p><span style="color: #000000;">En la variable <strong>$KeyResponse.value</strong> ya tendríamos nuestro secret <strong>AppId</strong>, podemos ver su valor si activamos el trigger de la función:</span></p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-237" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/ExecutionAzureFunction.jpg" alt="" width="391" height="287" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/ExecutionAzureFunction.jpg 569w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/ExecutionAzureFunction-300x220.jpg 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/ExecutionAzureFunction-454x333.jpg 454w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/ExecutionAzureFunction-505x370.jpg 505w" sizes="auto, (max-width: 391px) 100vw, 391px" /></p>
<p><span style="color: #000000;"><em>No olvidéis que la <strong>seguridad</strong> sustenta uno de los pilares principales de toda empresa y desarrollador, saquemos ese perfil <strong>DevOps</strong></em> que llevamos dentro <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.joselcaguilar.com/2018/06/azure-functions-msi-vs-key-vault-rest-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure SQL y Service Principals en PowerShell</title>
		<link>https://www.joselcaguilar.com/2018/06/autenticacion-azure-sql-service-principal-en-powershell/</link>
					<comments>https://www.joselcaguilar.com/2018/06/autenticacion-azure-sql-service-principal-en-powershell/#respond</comments>
		
		<dc:creator><![CDATA[JoseLCAguilar]]></dc:creator>
		<pubDate>Thu, 07 Jun 2018 08:53:12 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Service Principals]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Aplicacion]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Active Directory]]></category>
		<category><![CDATA[Azure SQL]]></category>
		<category><![CDATA[AzureRM]]></category>
		<category><![CDATA[Service Principal]]></category>
		<guid isPermaLink="false">https://www.joselcaguilar.com/?p=191</guid>

					<description><![CDATA[¡Hola a tod@s! Después de [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="color: #000000;">¡Hola a tod@s!</span></p>
<p><span style="color: #000000;">Después de un tiempo sin escribir debido a motivos laborales y el máster de ciberseguridad a punto de finalizar, nos aventuraremos a realizar algo en lo que no encontré mucha documentación en la web, pero necesario para mejorar la <strong>seguridad</strong> en los mismos y centralizar la autenticación en AAD, exactamente explicaré cómo realizar una autenticación mediante un Service Principal en Azure SQL haciendo uso de nuestra gran arma: <strong>PowerShell</strong>.</span></p>
<p><span style="color: #000000;">Debemos de tener generado nuestro Service Principal, en caso de que así no sea, es tan sencillo como dirigirnos a <strong>Azure Active Directory</strong> y registrar una nueva aplicación de tipo <strong>Web App/API</strong> indicando un <strong>URI Endpoint</strong> cualquiera:</span></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-198" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-1024x675.jpg" alt="" width="640" height="422" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-1024x675.jpg 1024w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-300x198.jpg 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-768x506.jpg 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-500x329.jpg 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-744x490.jpg 744w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-562x370.jpg 562w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal-900x593.jpg 900w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-1-ServicePrincipal.jpg 1726w" sizes="auto, (max-width: 640px) 100vw, 640px" /><br />
<span style="color: #000000;">Apuntamos el <strong>Application Id</strong> que nos genera, además debemos de obtener un <strong>Secret</strong>, para ello nos vamos al apartado de <strong>Keys</strong> y generamos 1 con la fecha de expiración que deseemos apuntando ambos valores:</span></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-199" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-1024x514.jpg" alt="" width="640" height="321" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-1024x514.jpg 1024w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-300x151.jpg 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-768x386.jpg 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-500x251.jpg 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-976x490.jpg 976w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-737x370.jpg 737w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal-900x452.jpg 900w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/Step-2-ServicePrincipal.jpg 1878w" sizes="auto, (max-width: 640px) 100vw, 640px" /></p>
<p><span style="color: #000000;">Vale, pero&#8230; ¿Cómo va a reconocer el acceso mi <strong>Azure SQL</strong> si no lo he indicado en ningún sitio?</span></p>
<p><span style="color: #000000;">¡Vamos con ello!</span></p>
<p><span style="color: #000000;">Entramos en nuestra DB con un usuario con autenticación básica que sea administrador de la DB y ejecutamos la siguiente query <strong>T-SQL</strong> para crear el usuario desde un proveedor externo, le ponemos el rol que nos interese, en nuestro caso lo dejamos como <strong>db_owner</strong>:</span></p>
<pre class="line-numbers"><code class="language-sql">CREATE USER [ApplicationName] FROM EXTERNAL PROVIDER
GO
ALTER ROLE db_owner ADD MEMBER[ApplicationName]</code></pre>
<p><span style="color: #000000;">Para llegar a nuestro objetivo, tenemos que estudiar las diferentes posibilidades:</span></p>
<ul>
<li><strong>Invoke-SQLCMD:</strong> No permite modificar en el ConnectionString la posibilidad de añadirle un token de acceso, además, el campo Authentication cuenta con:
<ul>
<li>Autenticación integrada (hace uso de SSO y nuestro cliente unido a dominio).</li>
<li>Autenticación mediante Azure AD con Usuario/Contraseña.</li>
<li>Autenticación básica SQL Server.</li>
</ul>
</li>
<li><strong>ADO.NET:</strong> Si estudiamos la conexión que se realiza desde C# (mucho más documentada, todo hay que decirlo), podemos observar que tenemos ya algo que nos puede servir dentro de las propiedades de la clase <a href="https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection(v=vs.110).aspx">System.Data.SqlClient.SqlConnection</a> <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.accesstoken(v=vs.110).aspx">AccessToken</a>.</li>
</ul>
<p><span style="color: #000000;">Por lo tanto, tenemos claro el camino que tenemos que seguir, ahora tenemos otras 2 opciones, ¿me compilo una librería en <strong>C#</strong> y realizo la llamada posteriormente o intentamos hacer uso de la clase de manera directa desde PowerShell?</span></p>
<p><span style="color: #000000;">Por temas de performance, vamos a intentar ir por la segunda opción, ¿pero cómo obtengo Access Token si además me vendrá cifrado y en <strong>JSON</strong>?</span></p>
<p><span style="color: #000000;">Para ello, en primer lugar autenticaríamos con nuestro <strong>Service Principal</strong> que podría obtener el Secret de nuestro Service Principal de un <a href="https://azure.microsoft.com/es-es/services/key-vault/">Azure Key Vault</a> por ejemplo, evitando así tener passwords hardcoded:</span></p>
<pre class="line-numbers"><code class="language-powershell">$securePassword = ConvertTo-SecureString $appKey -AsPlainText -Force
$secureCredential = New-Object System.Management.Automation.PSCredential($appId, $securePassword)
Connect-AzureRmAccount -ServicePrincipal -Credential $secureCredential -TenantId $tenantId -SubscriptionId $subscriptionId</code></pre>
<p><span style="color: #000000;">A continuación, procedemos a generar la función que nos devuelva nuestro Access Token solicitándolo al audience correspondiente (<a href="https://database.windows.net/">https://database.windows.net/</a>&#8220;) mediante una petición de REST API diréctamente a Azure, aquí es necesario que le pasemos en las variables correspondientes el <strong>Application Id</strong> y <strong>Secret Key</strong>:</span></p>
<pre class="line-numbers"><code class="language-powershell">function Get-AccessToken{
    $TokenEndpoint = {https://login.windows.net/{0}/oauth2/token} -f $tenantId 
    $ARMResource = "https://database.windows.net/";

    $Body = @{
            'resource'= $ARMResource
            'client_id' = $appId
            'grant_type' = 'client_credentials'
            'client_secret' = $appKey
    }
    $params = @{
        ContentType = 'application/x-www-form-urlencoded'
        Headers = @{'accept'='application/json'}
        Body = $Body
        Method = 'Post'
        URI = $TokenEndpoint
    }
    $token = Invoke-RestMethod @params
    return $token.access_token
}</code></pre>
<p><span style="color: #000000;">Una vez que tenemos nuestro token, podemos comprobar que es correcto <strong>decodificándolo</strong> con <a href="https://jwt.io">jwt.io</a>, tenemos que obtener algo parecido a:</span></p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-193 size-large" src="https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-1024x554.png" alt="" width="640" height="346" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-1024x554.png 1024w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-300x162.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-768x415.png 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-500x270.png 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-906x490.png 906w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-684x370.png 684w, https://www.joselcaguilar.com/wp-content/uploads/2018/06/AccessToken-900x487.png 900w" sizes="auto, (max-width: 640px) 100vw, 640px" /></p>
<p><span style="color: #000000;">Por último, nos creamos la función de conexión que lanzará la query que le pasemos como parámetro contra <strong>Azure SQL</strong> y cerrará la conexión para evitar tener sockets abiertos, aquí es necesario que añadamos el <strong>nombre</strong> del servidor SQL y la <strong>DB</strong> a la cual queremos conectar:</span></p>
<pre class="line-numbers"><code class="language-powershell">function SQLConnection {
    param(
     [string]$query
    )
    $ConnectionString = 'Server=&lt;YOUR SQL SERVER&gt;.database.windows.net;Database=&lt;YOUR DB&gt;;Integrated Security=False;'
    $connection = New-Object -TypeName System.Data.SqlClient.SqlConnection($ConnectionString)
    $connection.AccessToken = Get-AccessToken
    $connection.Open()
    $cmd=new-object system.Data.SqlClient.SqlCommand($query,$connection)
    $cmd.CommandTimeout = 30
    $DataSet = New-Object system.Data.DataSet
    $Adapter = New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
    [void]$Adapter.fill($DataSet)
    $value = $DataSet.Tables[0]
    $connection.Close()
    return $value
}</code></pre>
<p>&nbsp;</p>
<p><span style="color: #000000;">¡Espero que hayáis aprendido tanto como yo al escribir esta entrada!</span> <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.joselcaguilar.com/2018/06/autenticacion-azure-sql-service-principal-en-powershell/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure PowerShell Contexts</title>
		<link>https://www.joselcaguilar.com/2018/02/azure-powershell-contexts/</link>
					<comments>https://www.joselcaguilar.com/2018/02/azure-powershell-contexts/#respond</comments>
		
		<dc:creator><![CDATA[JoseLCAguilar]]></dc:creator>
		<pubDate>Tue, 27 Feb 2018 10:23:56 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[AzureRM]]></category>
		<category><![CDATA[cmdlet]]></category>
		<category><![CDATA[Context]]></category>
		<guid isPermaLink="false">https://www.joselcaguilar.com/?p=143</guid>

					<description><![CDATA[¡Buenos días a tod@s! Me [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="color: #000000;">¡Buenos días a tod@s!</span></p>
<p><span style="color: #000000;">Me gustaría comenzar esta entrada poniéndonos todos en contexto (nunca mejor dicho) y siguiendo lo comentado en la primera entrada: </span><a href="https://www.joselcaguilar.com/2018/02/hi-world/">Hi World!</a></p>
<p><span style="color: #000000;">A final de septiembre de 2017, Microsoft incluyó </span><span style="color: #000000;">un cmdlet muy interesante: <strong>Azure Context Autosave</strong>, éste funciona desde la versión 4.4.0 del módulo de <a href="https://docs.microsoft.com/es-es/powershell/azure/servicemanagement/install-azure-ps?view=azuresmps-4.0.0">AzureRM</a> de PowerShell, en el momento que estoy escribiendo estas líneas, estamos ya por la versión 5.4.0.</span></p>
<p><span style="color: #000000;">Ante el tedioso motivo de tener que insertar la credencial cada vez que queremos interactuar con nuestras suscripciones de Azure o de nuestros clientes al tener varias cuentas, tenemos que hacer uso en numerosas ocasiones de:</span></p>
<pre class="line-numbers"><code class="language-powershell">Login-AzureRmAccount</code></pre>
<p><span style="color: #000000;"><img loading="lazy" decoding="async" class=" wp-image-147 aligncenter" src="https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-300x280.png" alt="" width="329" height="307" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-300x280.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-768x718.png 768w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-356x333.png 356w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-524x490.png 524w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-396x370.png 396w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/1-900x841.png 900w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/1.png 913w" sizes="auto, (max-width: 329px) 100vw, 329px" /></span><br />
<span style="color: #000000;"> En este ejemplo, vamos a enseñar cómo hacer uso del nuevo cmdlet para 2 cuentas diferentes gracias a las plantillas JSON de ARM siguiendo los siguientes pasos:</span></p>
<ul>
<li>
<h6><span style="color: #000000;">Habilitamos AzureRM Context, que nos guardará la información en: <strong>%AppData%\Roaming\Windows Azure PowerShell</strong> para ello, ejecutamos el siguiente cmdlet:</span></h6>
</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">Enable-AzureRmContextAutosave</code></pre>
<ul>
<li>
<h6><span style="color: #000000;">Agregamos las 2 cuentas mediante el cmdlet:</span></h6>
</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">Connect-AzureRmAccount</code></pre>
<ul>
<li>
<h6><span style="color: #000000;">Nos fijamos en el nombre de los 2 contextos que se han creado en: <strong>%AppData%\Roaming\Windows Azure PowerShell\AzureRmContext.json </strong>ó también ejecutando el siguiente cmdlet:</span></h6>
</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">Get-AzureRMContext -ListAvailable</code></pre>
<p style="text-align: center;"><span style="color: #000000;"><img loading="lazy" decoding="async" class="alignnone wp-image-148" src="https://www.joselcaguilar.com/wp-content/uploads/2018/02/2-300x157.png" alt="" width="319" height="167" srcset="https://www.joselcaguilar.com/wp-content/uploads/2018/02/2-300x157.png 300w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/2-500x262.png 500w, https://www.joselcaguilar.com/wp-content/uploads/2018/02/2.png 587w" sizes="auto, (max-width: 319px) 100vw, 319px" /></span></p>
<ul>
<li>
<h6><span style="color: #000000;">Renombramos el contexto con un nombre familiar, como podemos ver en la imagen de más arriba se han renombrado ambos contextos, uno pertenece a &#8220;<strong>Yoda</strong>&#8221; y el otro personal &#8220;<strong>JoseLCAguilar</strong>&#8220;, para ello hacemos uso del siguiente cmdlet en ambos contextos:</span></h6>
</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">Rename-AzureRMContext "NombreOriginal" "NombreFamiliar"</code><code class="language-powershell"></code></pre>
<ul>
<li>
<h6><span style="color: #000000;">Para cambiar de un contexto a otro, símplemente ejecutamos lo siguiente:</span></h6>
</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">Select-AzureRMContext "NombreFamiliar"</code></pre>
<ul>
<li>
<h6><span style="color: #000000;">Por último, para eliminar un contexto, podemos hacer uso de:</span></h6>
</li>
</ul>
<pre class="line-numbers"><code class="language-powershell">Remove-AzureRmAccount -ContextName "NombreDeContexto"</code></pre>
<p><span style="color: #000000;">Si nos fijamos, al abrir y cerrar la sesión de PowerShell, <strong><span style="color: #ff0000;">¡voilá!</span></strong> podremos ver que automágicamente el equipo nos coge el último contexto usado y podemos hacer uso de todos los cmdlets de Azure sin tener que escribir las credenciales una y otra vez en nuestra consola de PowerShell.</span></p>
<p><span style="color: #000000;">Podéis encontrar más info </span><a href="https://docs.microsoft.com/en-us/powershell/azure/context-persistence?view=azurermps-5.3.0">aquí</a><span style="color: #000000;">.</span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.joselcaguilar.com/2018/02/azure-powershell-contexts/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Almacenamiento en caché de páginas con Disk: Enhanced 
Caché de base de datos usando Disk (En toda la solicitud modification query)

Served from: www.joselcaguilar.com @ 2026-09-10 20:17:30 by W3 Total Cache
-->