Azure MSI:用户“”登录失败

Posted

技术标签:

【中文标题】Azure MSI:用户“”登录失败【英文标题】:Azure MSI: Login failed for user '' 【发布时间】:2018-09-11 12:09:08 【问题描述】:

我正在尝试使用 MSI 令牌从应用服务连接到数据库,并且正在获取

Login failed for user ''.

当我使用 ARM 部署应用服务时,我生成了一个输出,确保它创建了一个服务主体:

 
  "principalId":"98f2c1f2-0a86-4ff1-92db-d43ec0edxxxx","
  tenantId":"e6d2d4cc-b762-486e-8894-4f5f440dxxxx",
  "type":"SystemAssigned"
 

我还检查了 Kudu 的环境变量并且有:

MSI_ENDPOINT = http://127.0.0.1:41239/MSI/token/
MSI_SECRET = 7C1B16Fxxxxxxxxxxxxx

我在 Azure 门户中提供了如下连接字符串:

Data Source=nzmoebase0001bt.database.windows.net;Initial Catalog=nzmoebase0001bt;Connect Timeout=300;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

作为越位,MSI(理论上)允许人们从源代码剪切/粘贴到公共论坛而不用担心留下秘密,这不是很酷吗?!只是说……现在……要是我能让它工作就好了!!!

我已将主体作为所有者添加到数据库中...

但我仍然得到:

Login failed for user ''.

我还应该尝试什么?

谢谢。

@juunas:正在使用以下方式添加令牌:

    static async Task AttachAccessTokenToDbConnection(IDbConnection dbConnection)
    
        SqlConnection sqlConnection = dbConnection as SqlConnection;
        if (sqlConnection == null)
        
            return;
        
        string msiEndpoint = Environment.GetEnvironmentVariable("MSI_ENDPOINT");
        if (string.IsNullOrEmpty(msiEndpoint))
        
            return;
        

        var msiSecret = Environment.GetEnvironmentVariable("MSI_SECRET");
        if (string.IsNullOrEmpty(msiSecret))
        
            return;
        

        // To get around:
        // "Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string."
        var terms = new[] "UserID","Password","PWD=","UID=" ;
        string connectionString = dbConnection.ConnectionString;

        foreach (var term in terms)
        
            if (connectionString.Contains(term, StringComparison.InvariantCultureIgnoreCase))
            
                return;
            
        

        string accessToken = await AppCoreDbContextMSITokenFactory.GetAzureSqlResourceTokenAsync();
        sqlConnection.AccessToken = accessToken;
    

更新: 一些进展(不完全确定发生了什么变化),来自实体框架

This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection.

我根据网上的几个建议添加了Persist Security Info = True,但没有太大变化。

Data Source=nzmoebase0001bt.database.windows.net;Initial Catalog=nzmoebase0001bt;MultipleActiveResultSets=False;Persist Security Info = True;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

根据@evilSnobu,我终于开始追踪并捕获了令牌:

 .eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI....

使用 jwt.io 解码得到的结果:


  "typ": "JWT",
  "alg": "RS256",
  "x5t": "FSimuFrFNoC0sJXGmv13nNZceDc",
  "kid": "FSimuFrFNoC0sJXGmv13nNZceDc"
.
  "aud": "https://database.windows.net/",
  "iss": "https://sts.windows.net/e6d2d4cc-b762-486e-8894-4f5f440dxxxx/",
  "iat": 1522783025,
  "nbf": 1522783025,
  "exp": 1522786925,
  "aio": "Y2NgYPjNdyJd9zrzpLavJSEzNIuPAAA=",
  "appid": "d1057cea-461b-4946-89a9-d76439c2xxxx",
  "appidacr": "2",
  "e_exp": 262800,
  "idp": "https://sts.windows.net/e6d2d4cc-b762-486e-8894-4f5f440dxxxx/",
  "oid": "98f2c1f2-0a86-4ff1-92db-d43ec0edxxxx",
  "sub": "98f2c1f2-0a86-4ff1-92db-d43ec0edxxxx",
  "tid": "e6d2d4cc-b762-486e-8894-4f5f440dxxxx",
  "uti": "59bqKWiSL0Gf0bTCI0AAAA",
  "ver": "1.0"
.[Signature]

对于我未经训练的眼睛来说,哪个看起来很棒(?)。但我仍然得到:

System.Data.SqlClient.SqlException: Login failed for user ''.

这似乎来自与 EntityFramework 的启动计划检查过程的更深层次的消息联系:

[InvalidOperationException: This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection.]

非常感谢任何和所有建议。谢谢!

【问题讨论】:

您能否显示获取访问令牌并将其附加到数据库连接的代码? docs.microsoft.com/en-us/azure/sql-database/… 首先确保您获得了一个有效的令牌(打印出来),在jwt.ms 中查看它。我相信即使对于应用服务,您仍然需要遵循这几个步骤,尽管对此不太确定 - docs.microsoft.com/en-us/azure/active-directory/… 我已更新问题以添加您要求的信息。希望对您有所帮助。 您找到解决问题的方法了吗? 【参考方案1】:

我现在正在追查“此操作需要连接到 'master' 数据库”错误,遵循此文档: https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi

我认为在分配令牌后包含以下行是关键:

Database.SetInitializer<MyDatabaseContext>(null);

在我的例子中,我们有一些代码显式运行导致错误的实体框架迁移。当我们禁用它时,该应用开始按预期运行。

【讨论】:

我很困惑,添加这是否意味着迁移将不再运行?我也尝试遵循该文档,并且我完全希望在生产中运行时会返回此错误,因为我没有指定用户,但是当我指定用户时,我在本地得到 Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string. 并且Tried to get token using Managed Service Identity. Access token could not be acquired. Connection refused 正在生产中。

以上是关于Azure MSI:用户“”登录失败的主要内容,如果未能解决你的问题,请参考以下文章

Azure 数据工厂复制活动失败。用户登录失败

Azure 突触分析 |用户“<token-identified principal>”登录失败

SQL 异常:用户登录失败

登录 Azure Web 应用程序失败并显示“AADSTS50079:用户需要使用多重身份验证”

SqlException (0x80131904):在 Azure 上托管的 .NET 6 WebAPI 上的用户“dbuser”登录失败

登录 Azure 容器注册表时 SSL 证书验证失败