3

Google Cloud Storage(GCS)に直接ファイルをアップロードするための署名付きURLを作成しようとしています。私はを使ってこの作業を行い、ポリシーを利用してthis Github exampleを使用しました。ベストプラクティスごとに、私はPUTを使用するためにリファクタリングとSignatureDoesNotMatchエラーになっている:私の署名文字列を構築GCS PUTリクエストのGAEで署名されたURL

  1. <?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>PUT 
    
    
    123456789 
    /mybucket/mycat.jpg</StringToSign></Error> 
    
    creating a signed URL with a program上のドキュメント毎の

    GCP example Python codeを、私はこのプロセスをしていますそれは

  2. が結果をコード
  3. URL(Pythonの例はしかしこれを実行しないエンコードすること
  4. BASE64に署名
  5. ...

これはGoogle App Engine(GAE)アプリで実行されているため、サービスアカウントのユーザー用にJSONキーファイルを取得する必要はなく、App Identity Servicesを使用して署名する必要があります。ここに私のコードは、フラスコのプロジェクト内です:

google_access_id = app_identity.get_service_account_name() 
expires = arrow.utcnow().replace(minutes=+10).replace(microseconds=0).timestamp 
resource = '/mybucket/mycat.jpg' 

args = self.get_parser.parse_args() 
signature_string = 'PUT\n' 
# take MD5 of file being uploaded and its content type, if provided 
content_md5 = args.get('md5') or '' 
content_type = args.get('contenttype') or '' 
signature_string = ('PUT\n' 
        '{md5}\n' 
        '{content_type}\n' 
        '{expires}\n' 
        '{resource}\n').format(
        md5=content_md5, 
        content_type=content_type, 
        expires=expires, 
        resource=resource) 
log.debug('signature string:\n{}'.format(signature_string)) 
_, signature_bytes = app_identity.sign_blob(signature_string) 
signature = base64.b64encode(signature_bytes) 
# URL encode signature 
signature = urllib.quote(signature) 
media_url = 'https://storage.googleapis.com{}'.format(resource) 
return dict(GoogleAccessId=google_access_id, 
      Expires=expires, 
      Signature=signature, 
      bucket='mybucket', 
      media_url='{}?GoogleAccessId={}&Expires={}&Signature={}'.format(media_url, google_access_id, expires, signature)) 

log.debug文は完全に上記のGCS XMLエラー応答に署名と一致する署名ファイルを印刷します。一致すれば、なぜアップロードできないのですか?

gsutilを使用すると、同じGAEサービスアカウントを使用して署名付きURLを作成することができ、Postmanでもうまく動作します。私はgsutilの署名をURLエンコードしていますが、自分で署名したURLを作成しても、どちらの方法でも問題にはならないと思われます。GCSはPUTリクエストを取得し、署名が一致しないと訴えますログに記録されたデバッグメッセージ。私はまた元の署名文字列の後ろに\ nを付けて試しました。

EDIT:それはそれに署名した後、私はBase64 encodes the Policy before it singsと再びを踏襲POST例。私はこの手法をPUTシグネチャの作成で試してみましたが、違いはありませんでした。

+0

'md5'または 'contenttype' argsを指定していますか?実際のリクエストでは、リクエスト自体にリクエストが指定されていないようです。あなたのデバッグ文で生成される値は ''要素の値と正確に一致しますか? –

+0

私の要求にmd5やコンテンツタイプの詳細が含まれていないし、署名付き文字列にも指定されていない。これまでのところ内容は全く同じであることが分かります。私が署名した文字列は、返されたXML値と 'SignToString' – hamx0r

答えて

0

答えはSOと他の場所にあるContent-Typeヘッダーを使用する必要があることに他の答えがあります。これは部分的には真実ですが、私の主な問題点ではっきりしません。GCSに読み書きできる「エディタ」の権限を持つデフォルトのGAEサービスアカウントに依存していました。私は、そのアカウントからキーファイルを作った後、私は、この手がかりを与えたgsutilでそれを使用する:

[email protected] does not have permissions on gs://mybucket/cat.jpg, using this link will likely result in a 403 error until at least READ permissions are granted 

そこにファイルをPUTしようとしたとき、私はGCSからのエラーを取得したいことを右でしたが、それはwasn t 404エラー、質問に表示されたエラーはSignatureDoesNotMatchでした。

ソリューション2部分だった:

  1. はデフォルトGAEサービスを与える権限の "ストレージ" のセットからより多くの権限をアカウント:
    1. ストレージオブジェクトの作成者
    2. ストレージオブジェクトビューア
  2. ファイルにGCSを挿入するときは、必ずContent-Typeヘッダーを使用してください。これはSiで指定していないためです文字列を署名するには、デフォルトでtext/plainになり、ヘッダーにその文字列が必要です。

一つの最終観察:私はIAMコンソールから新しいJSONキーファイルを作成するまで、私は自分のアカウントに適切な権限を追加した後でも、私はまだgsutilので警告を受けました。さらに、IAMコンソールに権限が設定されていても、gsutilと古いキーファイルで作成された署名付きURLは機能しませんでした(SignatureDoesNotMatchエラー)。 GAE上で実行されているPythonコードは、更新なしで正常に動作しました.IAMとContent-Headersで一致するパーミッションが必要でした。

関連する問題