1

We want to use AzureSqlServer with ActiveDirectoryMSI authentication as well as token-based authentication and We are able to execute successfully from VM created in Azure network and added as a member of the Azure AD group. For that, we have created Contained user by following the link

https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-sql

And added the VM as part of AzureActiveDirectory by following this link

com.microsoft.sqlserver.jdbc.SQLServerException: MSI Token failure: Failed to acquire token from MSI Endpoint

And we are able to access the SQL data without providing username and password using both IMDS server and able to retrieve the token using http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fdatabase.windows.net%2F

and

ActiveDirectorMSI URIString jdbc:sqlserver://azuresqlserverNAME:1433;databaseName=DatabaseNAME;Authentication=ActiveDirectoryMsi; .

But when it comes to access from Onprem Windows/Linux/Mac machine we are not able to access Azure SQL server

Can someone please suggest to me in terms of on-prem what needs to be done so we can access AzureSqlServer with ActiveDirectoryMSI Authentication as well as token-based authentication?

Ajay Kumar Jaiswal
  • 352
  • 1
  • 6
  • 24
  • As far as I knew, we cannot use Azure MSI on-premise. According to the situation, I suggest you use `EnvironmentCredential` to get token and connect Azure SQL:https://learn.microsoft.com/en-us/java/api/com.azure.identity.environmentcredential?view=azure-java-preview – Jim Xu Jun 23 '20 at 07:33
  • Hi, @JimXu thanks for replying can you please tell me what is the prereq to getting that token from the On-prem machine. I mean on-prem machine should be the part of Azure Active Directory to access the azure resource and both should be under the same network. If you can help with that would be a great aid for me. – Ajay Kumar Jaiswal Jun 23 '20 at 10:24
  • What do you mean `on-prem machine should be the part of Azure Active Directory`? – Jim Xu Jun 24 '20 at 02:05
  • @JimXu on-prem means out-side of the Azure network Like your personal operating system have added it as part of Azure Active Directory. – Ajay Kumar Jaiswal Jun 24 '20 at 10:43

1 Answers1

3

According to my test, if you want to connect Azure SQL on-premise machine, please refer to the following steps

  1. Create a service principal
az ad sp create-for-rbac -n 'name' --skip-assignment
  1. Add the service principal as Azure SQL database contained user.

  2. Set environment variable. Please set the following variable as the environment variable

AZURE_TENANT_ID: ID of the service principal's tenant. Also called its 'directory' ID.

AZURE_CLIENT_ID: the service principal's client ID

AZURE_CLIENT_SECRET: one of the service principal's client secrets
  1. SDK

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.0.7</version>
</dependency>
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>8.2.2.jre8</version>
</dependency>

  1. code
 public static void main( String[] args )
    {
     AccessToken token= GetAccessToken();
     SQLServerDataSource ds = new SQLServerDataSource();

        ds.setServerName("<>.database.windows.net"); // Replace with your server name.
        ds.setDatabaseName("demo"); // Replace with your database name.
        ds.setAccessToken(token.getToken());

        try (Connection connection = ds.getConnection(); 
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    
    }
    
    public static  AccessToken GetAccessToken() {
        DefaultAzureCredential creds = new DefaultAzureCredentialBuilder()
                .build();
        TokenRequestContext request = new TokenRequestContext();
        System.out.println("444");
        request.addScopes("https://database.windows.net//.default");
        String token;
        AccessToken accesstoken=creds.getToken(request).block();
        
        return accesstoken;
                
                
        
        
    }
Jim Xu
  • 21,610
  • 2
  • 19
  • 39
  • Thanks @jimxu it worked for me. Can we use multiple on-prem machines with the same environment variable provided in a different machine simultaneously? – Ajay Kumar Jaiswal Jun 25 '20 at 07:33
  • Yes you can do that. – Jim Xu Jun 25 '20 at 07:37
  • Thanks, @JimXu for being a life saviour. – Ajay Kumar Jaiswal Jun 25 '20 at 07:47
  • Hi @jimxu when I integrated with my application I'm kept getting the below error reactor.core.Exceptions$ReactiveException: javax.net.ssl.SSLHandshakeException: Unsupported curveId: 29 Here is the GitHub post https://github.com/Azure/azure-sdk-for-java/issues/12799 Could you please look into this and help me out. – Ajay Kumar Jaiswal Jul 14 '20 at 05:02
  • @AjayKumarJaiswal please try to upgrade sdk version to `com.azure:azure-identity:1.1.0-beta.4` and add `executorService()`. – Jim Xu Jul 14 '20 at 06:08
  • Hi @jimxu Even after using executerservice i'm getting error com.microsoft.aad.msal4j.MsalClientException: java.net.SocketException: Connection reset What is causing these errors still unknown for me? Can we get access token using Postman so I can write my custom code using httpclient and set it in datasource. – Ajay Kumar Jaiswal Jul 15 '20 at 07:36
  • @AjayKumarJaiswal Yes, you can do that – Jim Xu Jul 15 '20 at 07:41
  • Hi @JimXu i followed this and able to get the token and login in AzureSqlServer HttpPost post = new HttpPost("https://login.microsoftonline.com/{{tenent_ID}}}/oauth2/token"); List urlParameters = new ArrayList<>(); urlParameters.add(new BasicNameValuePair("grant_type", "client_credentials")); urlParameters.add(new BasicNameValuePair("client_id", "client_ID")); urlParameters.add(new BasicNameValuePair("client_secret", "client_secret")); urlParameters.add(new BasicNameValuePair("resource", "https://database.windows.net")); – Ajay Kumar Jaiswal Jul 17 '20 at 09:35
  • I followed this link https://www.c-sharpcorner.com/blogs/create-azure-service-principal-and-get-aad-auth-token But the problem is token get's expired, I'm not finding any way to get the refresh token. Now I'm stuck with getting refresh token, Can you suggest me how do I achieve this case. – Ajay Kumar Jaiswal Jul 17 '20 at 09:38