0

Google Cloud Platformでは、App Engineの柔軟な環境インスタンスをパブリックアクセスから保護するためのアイデンティティアウェアプロキシが導入されました。安全なアプリエンジンエンドポイントへのアクセスのためのGoogleクラウド機能の認証方法

これは缶やAPIエンドポイントを主催GAEにアクセスしているGoogleのクラウド機能から使用する必要がある場合は、それは完全には明らかではありません。

documentation(PythonとJavaの例)は、1)JWTトークンの生成、2)OpenIDトークンの作成、3)Authorization: Bearer TOKENヘッダー付きのGoogle App Engineへのリクエストの送信からなるIAP認証ワークフローを示します。承認は関数が呼び出されるたびに起こることがある場合

これは、クラウド機能を実行するために非常に複雑なようです。

担保GAEのエンドポイントにアクセスするには、Googleのクラウド機能のための別の方法はありますか?このdocで説明したように

答えて

2

あなたが保護されたアプリをIAPするGCFからの呼び出しを行いたい場合は、あなたが実際にIDトークンを使用する必要があります。 Nodejsには例がありませんので、thisを参考にしました(スタイルが間違っている可能性があります。これは初めてnodejに触れるためです)。通常のJWTのクレームセットとは異なり、スコープは含まれておらず、target_audienceを持つべきではありません。

/** 
* Make IAP request 
* 
*/ 
exports.CfToIAP = function CfToIAP (req, res) { 
    var crypto = require('crypto'), 
     request = require('request'); 
    var token_URL = "https://www.googleapis.com/oauth2/v4/token"; 
    // service account private key (copied from service_account.json) 
    var key = "-----BEGIN PRIVATE KEY-----\nMIIEvQexsQ1DBNe12345GRwAZM=\n-----END PRIVATE KEY-----\n"; 

    // craft JWT 
    var JWT_header = new Buffer(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString('base64'); 
    // prepare claims set 
    var iss = "[email protected]"; // service account email address (copied from service_account.json) 
    var aud = "https://www.googleapis.com/oauth2/v4/token"; 
    var iat = Math.floor(new Date().getTime()/1000); 
    var exp = iat + 120; // no need for a long linved token since it's not cached 
    var target_audience = "12345.apps.googleusercontent.com"; // this is the IAP client ID that can be obtained by clicking 3 dots -> Edit OAuth Client in IAP configuration page 
    var claims = { 
    iss: iss, 
    aud: aud, 
    iat: iat, 
    exp: exp, 
    target_audience: target_audience 
    }; 
    var JWT_claimset = new Buffer(JSON.stringify(claims)).toString('base64'); 
    // concatenate header and claimset 
    var unsignedJWT = [JWT_header, JWT_claimset].join('.'); 
    // sign JWT 
    var JWT_signature = crypto.createSign('RSA-SHA256').update(unsignedJWT).sign(key, 'base64'); 
    var signedJWT = [unsignedJWT, JWT_signature].join('.'); 
    // get id_token and make IAP request 
    request.post({url:token_URL, form: {grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion:signedJWT}}, function(err,res,body){ 
    var data = JSON.parse(body); 
    var bearer = ['Bearer', data.id_token].join(' '); 
    var options = { 
     url: 'https://1234.appspot.com/', // IAP protected GAE app 
     headers: { 
     'User-Agent': 'cf2IAP', 
     'Authorization': bearer 
     } 
    }; 
    request(options, function (err, res, body) { 
     console.log('error:', err); 
    }); 
    }); 
    res.send('done'); 
}; 

/** 
* package.json 
* 
*/ 

{ 
    "name": "IAP-test", 
    "version": "0.0.1", 
    "dependencies": { 
    "request": ">=2.83" 
    } 
} 

更新:より良いオプションは、メタデータ・サーバを使用することですので、バンドルサービスアカウントキーは、推奨されません。以下のサンプルは、Googleのアイデンティティおよびアクセス管理(IAM)APIを有効にする必要があるとApp Engineのデフォルトのサービスアカウントは、サービスアカウント俳優の役割を持つべき機能するためには(デフォルトのエディタは十分ではありません):GAEは後ろに座っている

/** 
* Make request from CF to a GAE app behind IAP: 
* 1) get access token from the metadata server. 
* 2) prepare JWT and use IAM APIs projects.serviceAccounts.signBlob method to avoid bundling service account key. 
* 3) 'exchange' JWT for ID token. 
* 4) make request with ID token. 
* 
*/ 
exports.CfToIAP = function CfToIAP (req, res) { 
    // imports and constants 
    const request = require('request'); 
    const user_agent = '<user_agent_to_identify_your_CF_call>'; 
    const token_URL = "https://www.googleapis.com/oauth2/v4/token"; 
    const project_id = '<project_ID_where_CF_is_deployed>'; 
    const service_account = [project_id, 
          '@appspot.gserviceaccount.com'].join(''); // app default service account for CF project 
    const target_audience = '<IAP_client_ID>'; 
    const IAP_GAE_app = '<IAP_protected_GAE_app_URL>'; 

    // prepare request options and make metadata server access token request 
    var meta_req_opts = { 
    url: ['http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/', 
      service_account, 
      '/token'].join(''), 
    headers: { 
     'User-Agent': user_agent, 
     'Metadata-Flavor': 'Google' 
    } 
    }; 
    request(meta_req_opts, function (err, res, body) { 
    // get access token from response 
    var meta_resp_data = JSON.parse(body); 
    var access_token = meta_resp_data.access_token; 

    // prepare JWT that is {Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature} 
    // https://developers.google.com/identity/protocols/OAuth2ServiceAccount for more info 
    var JWT_header = new Buffer(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString('base64'); 
    var iat = Math.floor(new Date().getTime()/1000); 
    // prepare claims set and base64 encode it 
    var claims = { 
     iss: service_account, 
     aud: token_URL, 
     iat: iat, 
     exp: iat + 60, // no need for a long lived token since it's not cached 
     target_audience: target_audience 
    }; 
    var JWT_claimset = new Buffer(JSON.stringify(claims)).toString('base64'); 

    // concatenate JWT header and claims set and get signature usign IAM APIs projects.serviceAccounts.signBlob method 
    var to_sign = [JWT_header, JWT_claimset].join('.');  
    // sign JWT using IAM APIs projects.serviceAccounts.signBlob method 
    var signature_req_opts = { 
     url: ['https://iam.googleapis.com/v1/projects/', 
      project_id, 
      '/serviceAccounts/', 
      service_account, 
      ':signBlob'].join(''), 
     method: "POST", 
     json: { 
     "bytesToSign": new Buffer(to_sign).toString('base64') 
     }, 
     headers: { 
     'User-Agent': user_agent, 
     'Authorization': ['Bearer', access_token].join(' ') 
     } 
    }; 
    request(signature_req_opts, function (err, res, body) { 
     // get signature from response and form JWT 
     var JWT_signature = body.signature; 
     var JWT = [JWT_header, JWT_claimset, JWT_signature].join('.'); 

     // obtain ID token 
     request.post({url:token_URL, form: {grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion:JWT}}, function(err, res, body){ 
     // use ID token to make a request to the IAP protected GAE app 
     var ID_token_resp_data = JSON.parse(body); 
     var ID_token = ID_token_resp_data.id_token; 
     var IAP_req_opts = { 
      url: IAP_GAE_app, 
      headers: { 
      'User-Agent': user_agent, 
      'Authorization': ['Bearer', ID_token].join(' ') 
      } 
     }; 
     request(IAP_req_opts, function (err, res, body) { 
      console.log('error:', err); 
     }); 
     }); 
    }); 
    }); 
    res.send('done'); 
}; 
+0

各クラウド機能要求を認証するためのパフォーマンスオーバーヘッドが発生する可能性があるかどうかを知っていますか? – shongololo

+0

追加の保護層としては、エンドツーエンドの待ち時間の影響はほとんどありませんが、インスタンスレベルでは認証が行われていないため、CPU時間に影響を与えてはいけません。 –

+0

実際には、推奨されていない秘密鍵をバンドルする必要があるため、これは良いアプローチではありません。より良いアプローチは、メタデータサーバーを使用することです。後でサンプルを更新します。 –

0

、あなたが使用してGoogleクラウドプラットフォーム(GCP)APIの認証を受けることができます:

1 - サービスアカウント(好ましい方法) - あなたのGCPプロジェクトに関連付けられているのGoogleアカウントを使用し、特定のユーザーとは対照的にアプリは、エンドユーザーに代わってリソースにアクセスする必要がある場合に使用 -

2 - ユーザーアカウント。

、3- APIキー - プライベートデータにアクセスする必要がないのAPIを呼び出すときに一般的に使用されます。

+0

元の投稿で参照されているドキュメントに従う必要があると思われるアイデンティティアウェア対策私は「GOOGLE_APPLICATION_CREDENTIALS」を設定するだけではIAPでは十分ではないという印象を受けています(私の努力では成功しませんでした)。 – shongololo

+0

アプリケーションのデフォルト資格証明を設定するだけで十分です。この[スレッド](https://developers.google.com/identity/protocols/application-default-credentials)で詳細を読むことができます。統合に問題がある場合は、ログを投稿してください。 – Kenworth

+0

クラウド機能の環境変数を設定する方法はありますか?それ以外の場合はどのようにGOOGLE_APPLICATION_CREDENTIALSを設定するのかわかりませんか? – shongololo

関連する問題