GCP servis hesapları son kullanıcıya ihtiyaç duymadan Google API'leri ile iletişim kurmanızı sağlayan kimlik doğrulama ve yetkilendirme birimleridir. Kimlik doğrulama bir istemcinin kim olduğu bilgisini, yetkilendirme ise neler yapabileceği bilgisini içerir.
Bir uygulamada servis hesapları genellikle, kullanıcı özel verisinden ziyade uygulamaya özgü veriye erişmek istendiğinde kullanıcıyı aradan çıkararak sunucudan sunucuya iletişim için kullanılır.
Örneğin, Google Cloud Storage kullanarak dosya yazıp okuma işlemleri yapan bir uygulama yazmak istiyorsunuz. Ek olarak, Gcs'deki dosyalarınızın herkese açık olması yerine, sadece uygulamanız tarafından erişilebilir olmasını istiyorsunuz. Rollerinde Gcs üzerinde gerekli yetkileri olan bir servis hesabı oluşturup, bu servis hesabının anahtarını sunucunuza ekleyerek okuma/yazma işlemlerini sunucular üzerinden (kullanıcıya ihtiyaç duymadan) halledebilirsiniz. Bu sayede kullanıcı tarafında herhangi bir hassas veri kaydetmenize de gerek kalmaz.
{
"headers": {
"normalizedNames": {},
"lazyUpdate": null
},
"status": 401,
"statusText": "Unauthorized",
"url": "urlToService",
"ok": false,
"name": "HttpErrorResponse",
"message": "Http failure response for urlToService: 401 Unauthorized",
"error": {
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Anonymous caller does not have storage.objects.create access to bucket bucketName.",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Anonymous caller does not have storage.objects.create access to bucket bucketName."
}
}
}
Kullanıcı Tarafından Yönetilen Servis Hesapları
Google'ın otomatik olarak tanımladığı servis hesaplarına ek olarak kullanıcı tarafından tanımlanan servis hesaplarıdır. Genellikle, güvenliğin ikinci planda kaldığı (örneğin yerel ve şirket içi ortamlarda) veya Google harici başka bulut sunucularınında çalışılıyorsa bu tip servis hesaplarına başvurulur.
[SERVİS_HESAP_ADI]@[PROJE_ID].iam.gserviceaccount.com
Google Bulut Platformu konsolunu kullanarak sadece birkaç adımda servis hesabı oluşturmak mümkün.
- Menüyü kullanarak Servis Hesapları sayfasına girin.
- Servis Hesabı Oluştur butonuna tıklayın.
- Açılan pencerede
- Servis hesabının yetkilerini tanımlayan bir isim girin.
- Servis hesabının yerine getirmesini istediğiniz rolleri girin.
- Anahtar dosyası indirmek için Yeni Bir Özel Anahtar Ver onay kutusunu işaretleyin.
- Özel anahtar için bir dosya formatı (p12 veya json) seçin.
- Oluştur butonuna tıklayın.
- Anahtar dosyasını kaydedin, daha sonra Google API çağrılarını yetkilendirmede kullanacaksınız.
Google Api Client kütüphanelerini kullanarak anahtar dosyayı işlemek mümkün. Aşağıdaki örnekler java dili ile Google Api Java Client kütüphanesi kullanılarak oluşturulmuştur.
Credential credential = GoogleCredential.fromStream(keyFileInputStream).createScoped(Collections.singleton("https://www.googleapis.com/auth/devstorage.read_write"), httpTransport, jsonFactory);
storage = new Storage.Builder(httpTransport, jsonFactory, credential).build();
Aynı işlem p12 formatında bir anahtar dosyası ve GoogleCredential.Builder metodunu kullanarak da gerçekleştirilebilir.
credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(serviceAccountId)
.setServiceAccountPrivateKeyFromP12File(p12File)
.setServiceAccountScopes(scopes)
.addRefreshListener(refreshListener)
.build();
storage = new Storage.Builder(httpTransport, jsonFactory, credential).build();
Bir kullanıcının kimliğine bürünmek istenildiğinde setServiceAccountUser metodu kullanılabilir. Ortak bir data kümesinin tutulduğu, bir google hesabına gerek duyulan bir sisteme erişim için bu metoddan faydalanılabilir.
credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(serviceAccountId)
.setServiceAccountPrivateKeyFromP12File(p12File)
.setServiceAccountScopes(scopes)
.setServiceAccountUser("[email protected]")
.build();
Google Tarafından Yönetilen Servis Hesapları
Google tarafından otomatik olarak oluşturulup projeye atanan servis hesaplarıdır. Bu hesapların her biri farklı Google hizmetlerini temsil eder ve her birinin Google Cloud Platform projenize belirli bir düzeyde erişimi vardır.
Eğer uygulamanız Compute Engine, Kubernetes Engine, App Engine flexible environment, veya Cloud Functions üzerinde çalışıyorsa ayrıca bir servis hesabı oluşturmanıza gerek kalmadan Google tarafından otomatik olarak oluşturulmuş Compute Engine varsayılan servis hesabını kullanabilirsiniz.
[PROJE_NUMARASI][email protected]
GoogleCredential credential = GoogleCredential.getApplicationDefault().createScoped(gcsScopes);
storage = new Storage.Builder(httpTransport, jsonFactory, credential).build();
Eğer uygulamanız Google App Engine standard environment üzerinde çalışıyorsa App Engine App Identity API kullanarak kimlik bilgilerine erişmek mümkün.
AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(scopes);
String accessToken = accessToken.getAccessToken();
Application Default Credentials
GoogleCredential.GetApplicationDefault() ile getirilen varsayılan kimlik bilgisi, ilk olarak GOOGLE_APPLICATION_CREDENTIALS çevre değişkeninin belirlenip belirlenmediğine bakar. Eğer belirlenmiş ise, karşılığındaki değerin gösterdiği dosyayı kullanır. Eğer belirlenmemiş ise Compute Engine, Kubernetes Engine, App Engine flexible environment, veya Cloud Functions sistemlerinin sağladığı kimlik bilgisini kullanır. Eğer iki durumda da kimlik bilgisine ulaşılamazsa, hata oluşur.
Özetlemek gerekirse,
- 1. GOOGLE_APPLICATION_CREDENTIALS çevre değişkeninin değeri mevcut ise, işaret ettiği değer anahtar dosya olarak kullanılır.
- 2. Projenin içinde bulunduğu sistemin sağladığı kimlik bilgisi kullanılır.
- 3. İki durumda da kimlik bilgisi bulunamazsa hata oluşur.
Eğer Google App Engine içerisinde çalışılıyorsa ve varsayılan App Engine servis hesabı yerine elle oluşturulmuş kullanıcı tarafından yönetilen bir servis hesabı kullanmak isteniyorsa, kod içerisinden erişilmek istenen her kaynakta yapılması gerektiği gibi, anahtar dosyasının yolu appengine-web.xml dosyasında kaynak olarak belirtilmelidir. Aksi takdirde App Engine dosyayı bulamayacaktır.
java.io.IOException: Error reading credential file from environment variable GOOGLE_APPLICATION_CREDENTIALS,
value 'private_key.json': File does not exist. at
com.google.api.client.googleapis.auth.oauth2.DefaultCredentialProvider.runningUsingEnvironmentVariable(DefaultCredentialProvider.java:199) at
com.google.api.client.googleapis.auth.oauth2.DefaultCredentialProvider.detectEnvironment(DefaultCredentialProvider.java:166) at
com.google.api.client.googleapis.auth.oauth2.DefaultCredentialProvider.getDefaultCredentialUnsynchronized(DefaultCredentialProvider.java:110) at
com.google.api.client.googleapis.auth.oauth2.DefaultCredentialProvider.getDefaultCredential(DefaultCredentialProvider.java:91) at
com.google.api.client.googleapis.auth.oauth2.GoogleCredential.getApplicationDefault(GoogleCredential.java:213)
<env-var name="GOOGLE_APPLICATION_CREDENTIALS" value="private_key.json" />
<resource-files>
<include path="/**.json" />
</resource-files>