-
Notifications
You must be signed in to change notification settings - Fork 5.1k
[PostgreSQL] Add Microsoft.Azure.PostgreSQL.Auth library #55231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to this project will be documented in this file. | ||
|
|
||
| The format is based on keep-a-changelog principles and this project adheres to semantic versioning. | ||
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
| - Implement Entra ID authentication libraries for Npgsql to connect to a PostgreSQL database | ||
|
|
||
| ### Changed | ||
| - | ||
|
|
||
| ### Fixed | ||
| - Remove dependency on DefaultAzureCredential in source library | ||
|
|
||
| ### Deprecated | ||
| - | ||
|
|
||
| ### Removed | ||
| - | ||
|
|
||
| ### Security | ||
| - | ||
|
|
||
| --- | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 17 | ||
| VisualStudioVersion = 17.0.31903.59 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Files", "Files", "{4D180A10-CB16-4781-BEB7-EAE2038A0993}" | ||
| ProjectSection(SolutionItems) = preProject | ||
| README.md = README.md | ||
| EndProjectSection | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{5D20AA90-6969-D8BD-9DCD-8634F4692FDA}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GettingStarted", "samples\GettingStarted\GettingStarted.csproj", "{8528AA1A-1D38-48FF-9234-F49492A460C1}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft", "Microsoft", "{7ECBF5AD-AE5E-07AC-33F2-F258A53C5EA9}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure", "Azure", "{A542B900-C6AB-CFD7-234F-C4052AF02FF1}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PostgreSQL", "PostgreSQL", "{4F6131AE-B29D-8566-B8CA-1A2AABE27274}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Auth", "Auth", "{93934517-16C9-C51A-8F2B-54760F50BDEB}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.PostgreSQL.Entra", "src\Microsoft\Azure\PostgreSQL\Auth\Microsoft.Azure.PostgreSQL.Auth.csproj", "{3E862DB4-B843-4361-94B5-8CF34402B511}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft", "Microsoft", "{8FEB4F0F-C974-64A2-0863-8577ABAC15AD}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure", "Azure", "{AC05A953-B9EF-C104-E53F-E15EBB9C3478}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PostgreSQL", "PostgreSQL", "{7164C26A-6C7C-D37D-98D2-1150AFE094DD}" | ||
| EndProject | ||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Auth", "Auth", "{290860F1-0C73-540D-3A79-AA6C3ABBD9C3}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.PostgreSQL.Entra.Tests", "tests\Microsoft\Azure\PostgreSQL\Auth\Microsoft.Azure.PostgreSQL.Auth.csproj", "{750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}" | ||
|
Comment on lines
+25
to
+37
|
||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Debug|x64 = Debug|x64 | ||
| Debug|x86 = Debug|x86 | ||
| Release|Any CPU = Release|Any CPU | ||
| Release|x64 = Release|x64 | ||
| Release|x86 = Release|x86 | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Debug|x64.Build.0 = Debug|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Debug|x86.Build.0 = Debug|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Release|x64.ActiveCfg = Release|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Release|x64.Build.0 = Release|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Release|x86.ActiveCfg = Release|Any CPU | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1}.Release|x86.Build.0 = Release|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Debug|x64.Build.0 = Debug|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Debug|x86.Build.0 = Debug|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Release|x64.ActiveCfg = Release|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Release|x64.Build.0 = Release|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Release|x86.ActiveCfg = Release|Any CPU | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511}.Release|x86.Build.0 = Release|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Debug|x64.Build.0 = Debug|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Debug|x86.Build.0 = Debug|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Release|x64.ActiveCfg = Release|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Release|x64.Build.0 = Release|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Release|x86.ActiveCfg = Release|Any CPU | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6}.Release|x86.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(NestedProjects) = preSolution | ||
| {8528AA1A-1D38-48FF-9234-F49492A460C1} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA} | ||
| {7ECBF5AD-AE5E-07AC-33F2-F258A53C5EA9} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} | ||
| {A542B900-C6AB-CFD7-234F-C4052AF02FF1} = {7ECBF5AD-AE5E-07AC-33F2-F258A53C5EA9} | ||
| {4F6131AE-B29D-8566-B8CA-1A2AABE27274} = {A542B900-C6AB-CFD7-234F-C4052AF02FF1} | ||
| {93934517-16C9-C51A-8F2B-54760F50BDEB} = {4F6131AE-B29D-8566-B8CA-1A2AABE27274} | ||
| {3E862DB4-B843-4361-94B5-8CF34402B511} = {93934517-16C9-C51A-8F2B-54760F50BDEB} | ||
| {8FEB4F0F-C974-64A2-0863-8577ABAC15AD} = {0AB3BF05-4346-4AA6-1389-037BE0695223} | ||
| {AC05A953-B9EF-C104-E53F-E15EBB9C3478} = {8FEB4F0F-C974-64A2-0863-8577ABAC15AD} | ||
| {7164C26A-6C7C-D37D-98D2-1150AFE094DD} = {AC05A953-B9EF-C104-E53F-E15EBB9C3478} | ||
| {290860F1-0C73-540D-3A79-AA6C3ABBD9C3} = {7164C26A-6C7C-D37D-98D2-1150AFE094DD} | ||
| {750B2A4F-9EF5-4CC5-8EF9-A93F4A1748F6} = {290860F1-0C73-540D-3A79-AA6C3ABBD9C3} | ||
| EndGlobalSection | ||
| EndGlobal | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| ## Overview | ||
|
|
||
| This library enables Microsoft Entra ID authentication for Azure Database for PostgreSQL using the Npgsql driver. It eliminates database password management by using secure, token-based authentication through Azure's identity platform. | ||
|
|
||
| ### Key Benefits | ||
|
|
||
| - **Passwordless Authentication**: Uses OAuth 2.0 access tokens instead of database passwords | ||
| - **Centralized Identity Management**: Leverages existing Entra ID users and groups | ||
| - **Zero Secrets**: No database credentials stored in application code | ||
| - **Automatic Token Handling**: Manages token acquisition and renewal transparently | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| **Azure Database for PostgreSQL Setup:** | ||
| - Azure Database for PostgreSQL server with Entra ID authentication enabled | ||
| - Entra ID administrator configured (to set up database users) | ||
| - Application's Entra ID identity created as a database user with appropriate permissions | ||
|
|
||
| **Application Identity (choose one):** | ||
| - **Managed Identity**: For applications running in Azure (App Service, Functions, VMs) | ||
| - **Service Principal**: For applications with client credentials | ||
| - **User Identity**: For development or interactive scenarios | ||
|
|
||
| **Example PostgreSQL Setup:** | ||
| ```sql | ||
| -- Connect as Entra ID administrator and create database user | ||
| CREATE ROLE "[email protected]" WITH LOGIN; | ||
| GRANT CONNECT ON DATABASE mydb TO "[email protected]"; | ||
| GRANT USAGE ON SCHEMA public TO "[email protected]"; | ||
| -- Grant additional permissions as needed | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| In your program, import the namespace `Microsoft.Azure.PostgreSQL.Auth` | ||
|
|
||
| ```csharp | ||
| using Microsoft.Azure.PostgreSQL.Auth; | ||
| ``` | ||
| Use the extension methods as needed: | ||
|
|
||
| ### Asynchronous Authentication (Recommended) | ||
| ```csharp | ||
| using Azure.Identity; | ||
|
|
||
| // Fill in with connection information to Azure PostgreSQL server | ||
| // Note: No username/password in connection string - authentication handled by Entra ID | ||
| var connectionString = "Host=myserver.postgres.database.azure.com;Database=mydb;Port=5432;SSL Mode=Require;"; | ||
| var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString); | ||
|
|
||
| // Use the async extension method for Entra authentication | ||
| // This will automatically: | ||
| // - Detect the current Azure identity (managed identity, service principal, or user) | ||
| // - Acquire a PostgreSQL-scoped access token | ||
| // - Configure the connection to use token-based authentication | ||
| var credential = new DefaultAzureCredential(); | ||
| await dataSourceBuilder.UseEntraAuthenticationAsync(credential); | ||
| ``` | ||
|
|
||
| ### Synchronous Authentication | ||
| ```csharp | ||
| using Azure.Identity; | ||
|
|
||
| // Fill in with connection information to Azure PostgreSQL server | ||
| var connectionString = "Host=myserver.postgres.database.azure.com;Database=mydb;Port=5432;SSL Mode=Require;"; | ||
| var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString); | ||
|
|
||
| // Use the sync extension method for Entra authentication | ||
| var credential = new DefaultAzureCredential(); | ||
| dataSourceBuilder.UseEntraAuthentication(credential); | ||
| ``` | ||
|
|
||
| ## Benefits | ||
|
|
||
| - **Enhanced Security**: No database passwords to manage or rotate | ||
| - **Simplified Deployment**: Works seamlessly with Azure managed identities | ||
| - **Compliance**: Supports enterprise identity governance and MFA requirements | ||
| - **Developer Experience**: Transparent authentication - existing Npgsql code works unchanged |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,72 @@ | ||||||
| // Copyright (c) Microsoft Corporation. | ||||||
| // Licensed under the MIT License. | ||||||
|
|
||||||
| using Azure.Identity; | ||||||
| using Npgsql; | ||||||
| using Microsoft.Azure.PostgreSQL.Auth; | ||||||
| using Microsoft.Extensions.Configuration; | ||||||
|
|
||||||
| namespace GettingStarted; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// This example enables Entra authentication before connecting to the database via NpgsqlConnection. | ||||||
| /// </summary> | ||||||
| public class CreateDbConnectionNpgsql | ||||||
| { | ||||||
| public static async Task Main(string[] args) | ||||||
| { | ||||||
| Console.WriteLine("=== Getting Started with Azure Entra Authentication for PostgreSQL ===\n"); | ||||||
|
|
||||||
| // Build configuration | ||||||
| var configuration = new ConfigurationBuilder() | ||||||
| .SetBasePath(Environment.CurrentDirectory) | ||||||
| .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) | ||||||
| .AddEnvironmentVariables() | ||||||
| .Build(); | ||||||
|
|
||||||
| // Read configuration values and build connection string once | ||||||
| var server = configuration["Host"]; | ||||||
| var database = configuration["Database"] ?? "postgres"; | ||||||
| var port = configuration.GetValue<int>("Port", 5432); | ||||||
| var connectionString = $"Host={server};Database={database};Port={port};SSL Mode=Require;"; | ||||||
|
|
||||||
| Console.WriteLine("--- Testing UseEntraAuthentication (sync) ---"); | ||||||
| await ExecuteQueriesWithEntraAuth(connectionString, useAsync: false); | ||||||
|
|
||||||
| Console.WriteLine("\n--- Testing UseEntraAuthenticationAsync ---"); | ||||||
| await ExecuteQueriesWithEntraAuth(connectionString, useAsync: true); | ||||||
|
|
||||||
| Console.WriteLine("\n=== Sample completed ==="); | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Show how to create a connection to the database with Entra authentication and execute some prompts. | ||||||
| /// </summary> | ||||||
| /// <param name="connectionString">The PostgreSQL connection string</param> | ||||||
| /// <param name="useAsync">If true, uses UseEntraAuthenticationAsync; otherwise uses UseEntraAuthentication</param> | ||||||
| private static async Task ExecuteQueriesWithEntraAuth(string connectionString, bool useAsync = false) | ||||||
| { | ||||||
|
|
||||||
| var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString); | ||||||
|
|
||||||
| // Here, we use the appropriate extension method provided by NpgsqlDataSourceBuilderExtensions.cs | ||||||
|
||||||
| // Here, we use the appropriate extension method provided by NpgsqlDataSourceBuilderExtensions.cs | |
| // Here, we use the appropriate extension method provided by the EntraIdExtension class |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworks>net8.0;net9.0</TargetFrameworks> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Npgsql" Version="8.0.5" /> | ||
| <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" /> | ||
| <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> | ||
| <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" /> | ||
| <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" /> | ||
| <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="8.0.0" /> | ||
| <PackageReference Include="Azure.Identity" Version="1.13.1" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <None Update="appsettings.json"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| </None> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\src\Microsoft\Azure\PostgreSQL\Auth\Microsoft.Azure.PostgreSQL.Auth.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "Host": "myserver.postgres.database.azure.com", | ||
| "Database": "mydatabase", | ||
| "Port": 5432 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CHANGELOG has a "Fixed" entry stating "Remove dependency on DefaultAzureCredential in source library" but this is a new library being added. The "Fixed" section should be empty or this should be in a different section, as there was no previous version to fix.