理解した
したがって、これを解決するには 2 つの方法があります。
オプション1:
ストレージ バケットの暗号化/復号化に使用されていた KMS キーにプロジェクトがアクセスできるようにしていませんでした。自分自身としてログインしているときに、cli で次のコマンドを実行してテストできました。
gsutil kms authorize -p PROJECTNAME -k projects/PROJECTNAME/locations/global/keyRings/KEYRINGNAME/cryptoKeys/KEYNAME
- 次に、サービス アカウントとしてログインし、ファイルをアップロードしようとしました。そうしたら成功しました。
オプション 2:
- クラウド コンソールを調べてみたところ、Encrypt Decrypt へのアクセスが必要なストレージ サービス アカウントが存在することがわかりました。このアカウントは、[ストレージ] > [設定] > [クラウド ストレージ サービス アカウント] の下に表示されます。
- GCP は実際の作業をこのアカウントに委任して、アップロード タスクを実行しているようです。そのため、バケットへのアクセスはありますが (明らかに、これはストレージ サービス アカウントであるため)、KMS アクセスはありませんでした。KMS 暗号化/復号化をこの SA に追加した後、gsutil の介入なしで自動的に機能するようになりました。
また、アップロード用の SA 資格情報の範囲を更新して、cloudkms と devstorage.full_control の両方を含めました。ただし、それが何かに影響したかどうかはわかりません。
元の質問:
マルチテナント ホスティング環境向けに、サービス アカウント、ストレージ バケット、および KMS キー リングとキーを自動的に作成するワークフローを作成しています。
KMS、SA、およびストレージのアクセス許可が制限されたサービス アカウントを持っています。このサービス アカウントは、他のサービス アカウントを作成し、それらが独自のテナント アイテムの管理者になることを許可します (例: テナントのサービス アカウントを作成すると、それを完全に制御できます)。テナントの KMS とバケット。ただし、他のテナントのものではありません)。
ただし、現在、新しいサービス アカウントでファイルをアップロードできるようにする際に問題が発生しています。必要なすべての権限があります。
1. KMS 管理者とそのキーリングの暗号化/復号化
2. ストレージ バケット管理者
しかし、そのサービス アカウントで何かをアップロードしようとすると、次のエラーが発生します。
[403] Errors [
Message[Permission denied on Cloud KMS key.
Please ensure that your Cloud Storage service
account has been authorized to use this key. ]
Location[ - ]
Reason[forbidden]
Domain[global]
アクセス許可の割り当てに使用しているコードと、バケットへのアクセスに使用するコードを次に示します。
class Program
{
private static string solutionLocation = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @".." + Path.DirectorySeparatorChar + ".." + Path.DirectorySeparatorChar + ".." + Path.DirectorySeparatorChar));
static void Main(string[] args)
{
//Deserialize the JSON File for use with other things
JSONCreds jsonCreds = JsonConvert.DeserializeObject<JSONCreds>(
File.ReadAllText(Path.Combine(solutionLocation, "gcp-general-sa.json")));
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
Path.Combine(solutionLocation, "gcp-general-sa.json"));
KeyManagementServiceClient client = KeyManagementServiceClient.Create();
StorageClient storageClient = StorageClient.Create();
//Collect Tenant ID for testing purposes
Console.WriteLine("Tenant ID?");
string TID = Console.ReadLine();
if (TID.Length > 23)
{
TID = TID.Substring(0, 23);
}
//Setting some variables that are used throughout
string keyID = "key-" + TID;
string keyRingName = "ring-" + TID;
string keyLocationID = "global";
string saName = "sa-" + TID;
//Create a Service Account for this agency
var newServiceAccount = CreateServiceAccount(jsonCreds.project_id, saName, saName);
//Create an API Key for this Service Account, and then decode it
var credential = GoogleCredential.GetApplicationDefault().CreateScoped(IamService.Scope.CloudPlatform);
var service = new IamService(new IamService.Initializer
{
HttpClientInitializer = credential
});
var newServiceAccountFullKey = service.Projects.ServiceAccounts.Keys.Create( new CreateServiceAccountKeyRequest(), "projects/-/serviceAccounts/" + newServiceAccount.Email).Execute();
var newServiceAccountKey = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(newServiceAccountFullKey.PrivateKeyData));
Console.WriteLine("Created Service Account Key For: " + newServiceAccountFullKey.Name);
//Create KMS Key Ring for this agency
KeyRing newKeyRing = CreateKeyRing(client, jsonCreds.project_id, keyLocationID, keyRingName);
//Create a KMS Key in that new Key Ring
CryptoKey newKey = CreateCryptoKey(client, jsonCreds.project_id, keyLocationID, newKeyRing.KeyRingName.KeyRingId, keyID);
//Create Bucket with specified Parameters
Bucket bucket = new Bucket
{
Location = "us-central1",
Name = TID,
StorageClass = StorageClasses.Standard,
Encryption = new Bucket.EncryptionData()
{
DefaultKmsKeyName = newKey.Name
}
};
var newStorageBucket = storageClient.CreateBucket(jsonCreds.project_id, bucket);
//Set permissions for the new Service Account for the new KeyRing and Bucket
AddMemberToKeyRingPolicy(client, jsonCreds.project_id, keyLocationID, newKeyRing.KeyRingName.KeyRingId, "custom_role_with_multiple_permissions", "serviceAccount:" + newServiceAccount.Email);
AddBucketIamMember(newStorageBucket.Name, "roles/storage.admin", "serviceAccount:" + newServiceAccount.Email);
//Testing uploading to the new bucket with the new account
var newSACredential = GoogleCredential.FromJson(newServiceAccountKey.ToString()).CreateScoped("https://www.googleapis.com/auth/cloudkms");
var storage = StorageClient.Create(newSACredential);
using (var fileStream = new FileStream("sample_image.png", FileMode.Open, FileAccess.Read, FileShare.Read))
{
storage.UploadObject(newStorageBucket.Name, "sample_image_uploaded.png", null, fileStream);
}
}
私が間違っているかもしれないアイデアはありますか?パーミッションの問題のようですが、その場で作成されるこの新しいサービス アカウントに割り当てられたストレージと KMS の両方で使用できるほぼすべてのものがあります。
完全なスタック トレース:
Google.GoogleApiException: Google.Apis.Requests.RequestError
Insufficient Permission [403]
Errors [
Message[Insufficient Permission] Location[ - ] Reason[insufficientPermissions] Domain[global]
]
at Google.Cloud.Storage.V1.StorageClientImpl.UploadHelper.CheckFinalProgress() in T:\src\github\google-cloud-dotnet\releasebuild\apis\Google.Cloud.Storage.V1\Google.Cloud.Storage.V1\StorageClientImpl.UploadObject.cs:204
at Google.Cloud.Storage.V1.StorageClientImpl.UploadHelper.Execute() in T:\src\github\google-cloud-dotnet\releasebuild\apis\Google.Cloud.Storage.V1\Google.Cloud.Storage.V1\StorageClientImpl.UploadObject.cs:154
at Google.Cloud.Storage.V1.StorageClientImpl.UploadObject(Object destination, Stream source, UploadObjectOptions options, IProgress`1 progress) in T:\src\github\google-cloud-dotnet\releasebuild\apis\Google.Cloud.Storage.V1\Google.Cloud.Storage.V1\StorageClientImpl.UploadObject.cs:97
at Google.Cloud.Storage.V1.StorageClientImpl.UploadObject(String bucket, String objectName, String contentType, Stream source, UploadObjectOptions options, IProgress`1 progress) in T:\src\github\google-cloud-dotnet\releasebuild\apis\Google.Cloud.Storage.V1\Google.Cloud.Storage.V1\StorageClientImpl.UploadObject.cs:70
at ConsoleApp1.Program.Main(String[] args) in /Users/btruman/Desktop/gcp_scripts/VOCA Onboarding/Program.cs:136