如何通过服务帐户从.NET授权调用GCP数据目录API?

时间:2020-06-19 19:43:01

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

我正在尝试调用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上运行

1 个答案:

答案 0 :(得分:0)

找到了解决问题的方法。

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

这是一个三步过程-:

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]
}

响应

目录搜索输出。

样品: enter image description here

*用于从.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权限。

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