【问题标题】:How to call GCP Data Catalog API from .NET authorizing via a Service Account?如何通过服务帐户从 .NET 授权调用 GCP 数据目录 API?
【发布时间】:2020-10-10 03:15:45
【问题描述】:

我正在尝试调用 GCP 数据目录 API 进行搜索。我在 GCP 中创建了一个服务帐号。

使用来自 Nuget 的 Google.Cloud.DataCatalog.V1 包。

DataCatalogClientBuilder dcb = new DataCatalogClientBuilder();

dcb.CredentialsPath =  "json.json";

DataCatalogClient dataCatalogClient = dcb.Build();

SearchCatalogRequest scr = new SearchCatalogRequest();
scr.Query = "vbeln";
PagedAsyncEnumerable < SearchCatalogResponse, SearchCatalogResult >  sdjh = 
dataCatalogClient.SearchCatalogAsync(scr);

a) SearchCatalog 没有返回结果 b) 我无法传递范围(定义项目、组织)

有什么错误吗。

在 .NET Framework 4.6.1 上运行

【问题讨论】:

    标签: c# oauth-2.0 google-api-dotnet-client service-accounts


    【解决方案1】:

    找到问题的解决方案。

    按照服务帐户的 OAuth2 执行的步骤 https://developers.google.com/identity/protocols/oauth2/service-account

    这是一个 3 步过程 - :

    a) 使用 RS256 算法创建 JWT 令牌,声明/有效负载为 -:

         { "iss", "<service-account>@<project-Id>.iam.gserviceaccount.com"},
         { "scope", "https://www.googleapis.com/auth/cloud-platform" },
         { "aud", "https://oauth2.googleapis.com/token" },
         { "iat", iat},
         { "exp", exp}
    
    var iat = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    var exp = DateTimeOffset.UtcNow.AddMinutes(60).ToUnixTimeSeconds(); \\ 60 mins usage
    

    *有关从 .NET 创建 RS256 JWT 令牌的完整代码,请参阅此答案的结尾

    b) 调用令牌 API https://oauth2.googleapis.com/token

    请求

    grant_type = urn:ietf:params:oauth:grant-type:jwt-bearer
    断言 = 步骤 1 中生成的 JWT

    回应

    {
        "access_token": "******************************************************",
        "expires_in": 3599,
        "token_type": "Bearer"
    }
    

    此access_token将用于调用实际API,有效期为1小时。

    c) 调用数据目录搜索 API:https://datacatalog.googleapis.com/v1/catalog:search

    方法:发帖

    请求

      Authorization Type : Bearer Token
      Token Value        : access_token received in Step b
    
    Body : 
    
    {
      "scope": {
        "includeProjectIds": [
               "project-id1"
               "project-id2"
        ],
        "includeOrgIds": [
          "orgid"  
        ]
      },
      "query": "tag:project-id1.test_template1.owner:ZZZZZ OR COLUMN:VBELN"  -- Search Tag, can be fetched from [Try It link][4] or [Search Guide][4]
    }
    

    回应

    目录搜索输出。

    示例:

    *从 .NET 创建 JWT 令牌以传递给 GCP OAuth 令牌 API 的代码 -:

    using JWT;
    using JWT.Algorithms;
    using JWT.Serializers;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using System;
    using System.Collections.Generic;
    using System.Security.Cryptography;
    
    namespace GCP
    {
        class JWTTokenGenerationForGCPOAuthTokenAPI
        {
    
    
            public static string GenerateJWTToken()
            {
                var rsaParams = ReadAsymmetricKeyParameter();
                var encoder = GetRS256JWTEncoder(rsaParams);
                var iat = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                var exp = DateTimeOffset.UtcNow.AddMinutes(60).ToUnixTimeSeconds();
    
                // create the payload according to your need 
                // iss is the Service Account Email ID
                var payload = new Dictionary<string, object>
                {
                    { "iss",   "<service-account>@<project-id>.iam.gserviceaccount.com"},
                    { "scope", "https://www.googleapis.com/auth/cloud-platform" },
                    { "aud",   "https://oauth2.googleapis.com/token" },
                    { "exp",    exp},
                    { "iat",    iat}
                };
                //Final token
                var token = encoder.Encode(payload, new byte[0]);
    
                return token;
            }
    
            private static IJwtEncoder GetRS256JWTEncoder(RSAParameters rsaParams)
            {
                var csp = new RSACryptoServiceProvider();
                csp.ImportParameters(rsaParams);
                var algorithm = new RS256Algorithm(csp, csp);
                var serializer = new JsonNetSerializer();
                var urlEncoder = new JwtBase64UrlEncoder();
                var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
    
                return encoder;
            }
    
    
    
            public static RSAParameters ReadAsymmetricKeyParameter()
    
    
            {
    
    \\ This key is fetched from the Service Account JSON File. 
    \\"private_key": "-----BEGIN PRIVATE KEY-----\n<long-code>-----END PRIVATE KEY-----\n",
    \\ pick <long-code> from above. Replace all \n with actual new line like shown below.
    
                    string pkey = @"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDSoGKK/Dzb8MBy
    ################################################################
    ################################################################
    ################################################################
    ################################################################
    twySMqKKWnIC/zZljrvp4w==";
    
    
    
                RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters1;
                var keyBytes = Convert.FromBase64String(pkey);
                var asymmetricKeyParameter = PrivateKeyFactory.CreateKey(keyBytes);
    
    
                rsaPrivateCrtKeyParameters1 = (RsaPrivateCrtKeyParameters)asymmetricKeyParameter;
    
                RSAParameters r = DotNetUtilities.ToRSAParameters(rsaPrivateCrtKeyParameters1);
    
                return r;
    
    
            }
        }
    }
    

    在 .NET Framework 4.6.1 中完成的代码

    Nuget 包:

    Bounty Castle - 安装包 BouncyCastle - 版本 1.8.6.1

    注意:需要 GCP 授权 服务帐号应拥有所有项目的数据目录查看者权限,数据目录必须搜索对象。

    即如果在 project-id1 中创建了服务帐户,并且在 project-id1 和 project-id2 上都需要搜索 它应该对 project-id1 和 project-id2 都具有 Data Catalog Viewer 权限。

    此方法可用于调用任何 GCP API,只需更改实际 API 的请求正文并向服务帐户提供所需的权限

    【讨论】:

      猜你喜欢
      • 2019-08-17
      • 2021-12-19
      • 2013-08-21
      • 2020-01-06
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多