서비스 계정으로 인증

이 주제에서는 서비스 계정으로 애플리케이션을 인증하는 방법을 설명합니다. 일반적인 인증 시나리오 및 전략을 포함하여 Google Cloud API 인증에 대한 일반적인 정보는 인증 개요를 참조하세요. 서비스 계정에 대한 자세한 내용은 Identity and Access Management 문서의 서비스 계정을 참조하세요.

인증 정보 자동으로 찾기

애플리케이션이 Google Cloud 환경 내에서 실행되고 해당 환경에 서비스 계정을 연결했다면 애플리케이션이 서비스 계정의 사용자 인증 정보를 검색할 수 있습니다. 그런 다음 애플리케이션이 사용자 인증 정보를 사용하여 Google Cloud API를 호출할 수 있습니다.

Compute Engine, Google Kubernetes Engine, App Engine, Cloud Run, Cloud Functions를 비롯한 다양한 Google Cloud 서비스의 리소스에 서비스 계정을 연결할 수 있습니다. 이 전략은 사용자 인증 정보를 수동으로 전달하는 것보다 편리하고 안전하기 때문에 이 전략을 사용하는 것이 좋습니다.

또한 애플리케이션에 Google Cloud 클라이언트 라이브러리를 사용하는 것이 좋습니다. Google Cloud 클라이언트 라이브러리는 애플리케이션 기본 사용자 인증 정보(ADC)라는 라이브러리를 사용하여 서비스 계정 사용자 인증 정보를 자동으로 찾습니다. ADC는 다음과 같은 순서로 서비스 계정 사용자 인증 정보를 찾습니다.

  1. 환경 변수 GOOGLE_APPLICATION_CREDENTIALS가 설정된 경우 ADC는 변수가 가리키는 서비스 계정 키 또는 구성 파일을 사용합니다.

  2. 환경 변수 GOOGLE_APPLICATION_CREDENTIALS가 설정되지 않은 경우 ADC는 코드를 실행 중인 리소스에 연결된 서비스 계정을 사용합니다.

    이 서비스 계정은 Compute Engine, Google Kubernetes Engine, App Engine, Cloud Run 또는 Cloud Functions에서 제공하는 기본 서비스 계정일 수 있습니다. 사용자가 만든 사용자 관리형 서비스 계정일 수도 있습니다.

  3. ADC에서 위 사용자 인증 정보 중 하나를 사용할 수 없는 경우 오류가 발생합니다.

다음 코드 예시는 애플리케이션 코드에서 ADC 라이브러리를 사용하는 방법을 보여줍니다. 이 예시를 실행하려면 Cloud Storage 클라이언트 라이브러리를 설치해야 합니다.

C#

public object AuthImplicit(string projectId)
{
    // If you don't specify credentials when constructing the client, the
    // client library will look for credentials in the environment.
    var credential = GoogleCredential.GetApplicationDefault();
    var storage = StorageClient.Create(credential);
    // Make an authenticated API request.
    var buckets = storage.ListBuckets(projectId);
    foreach (var bucket in buckets)
    {
        Console.WriteLine(bucket.Name);
    }
    return null;
}

Go


// implicit uses Application Default Credentials to authenticate.
func implicit() {
	ctx := context.Background()

	// For API packages whose import path is starting with "cloud.google.com/go",
	// such as cloud.google.com/go/storage in this case, if there are no credentials
	// provided, the client library will look for credentials in the environment.
	storageClient, err := storage.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer storageClient.Close()

	it := storageClient.Buckets(ctx, "project-id")
	for {
		bucketAttrs, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(bucketAttrs.Name)
	}

	// For packages whose import path is starting with "google.golang.org/api",
	// such as google.golang.org/api/cloudkms/v1, use NewService to create the client.
	kmsService, err := cloudkms.NewService(ctx)
	if err != nil {
		log.Fatal(err)
	}

	_ = kmsService
}

자바

static void authImplicit() {
  // If you don't specify credentials when constructing the client, the client library will
  // look for credentials via the environment variable GOOGLE_APPLICATION_CREDENTIALS.
  Storage storage = StorageOptions.getDefaultInstance().getService();

  System.out.println("Buckets:");
  Page<Bucket> buckets = storage.list();
  for (Bucket bucket : buckets.iterateAll()) {
    System.out.println(bucket.toString());
  }
}

Node.js

// Imports the Google Cloud client library.
const {Storage} = require('@google-cloud/storage');

// Instantiates a client. If you don't specify credentials when constructing
// the client, the client library will look for credentials in the
// environment.
const storage = new Storage();
// Makes an authenticated API request.
async function listBuckets() {
  try {
    const results = await storage.getBuckets();

    const [buckets] = results;

    console.log('Buckets:');
    buckets.forEach(bucket => {
      console.log(bucket.name);
    });
  } catch (err) {
    console.error('ERROR:', err);
  }
}
listBuckets();

PHP

// Imports the Cloud Storage client library.
use Google\Cloud\Storage\StorageClient;

function auth_cloud_implicit($projectId)
{
    $config = [
        'projectId' => $projectId,
    ];

    # If you don't specify credentials when constructing the client, the
    # client library will look for credentials in the environment.
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python

def implicit():
    from google.cloud import storage

    # If you don't specify credentials when constructing the client, the
    # client library will look for credentials in the environment.
    storage_client = storage.Client()

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

# project_id = "Your Google Cloud project ID"

require "google/cloud/storage"

# If you don't specify credentials when constructing the client, the client
# library will look for credentials in the environment.
storage = Google::Cloud::Storage.new project: project_id

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

수동으로 사용자 인증 정보 전달

애플리케이션이 서비스 계정이 연결되지 않은 환경에서 실행되는 경우 서비스 계정을 수동으로 만들어야 합니다. 그런 다음 서비스 계정과 연결된 사용자 인증 정보인 서비스 계정 키를 하나 이상 만들 수 있습니다. 그러면 서비스 계정 키가 애플리케이션에 수동으로 전달될 수 있습니다.

서비스 계정 만들기

다음 단계에서는 서비스 계정이 없는 경우 이를 만드는 방법을 설명합니다.

Cloud Console

서비스 계정을 만듭니다.

  1. Cloud Console에서 서비스 계정 만들기 페이지로 이동합니다.

    서비스 계정 만들기로 이동
  2. 프로젝트를 선택합니다.
  3. 서비스 계정 이름 필드에 이름을 입력합니다. Cloud Console은 이 이름을 기반으로 서비스 계정 ID 필드를 채웁니다.

    서비스 계정 설명 필드에 설명을 입력합니다. 예를 들면 Service account for quickstart입니다.

  4. 만들기를 클릭합니다.
  5. 역할 선택 필드를 클릭합니다.

    빠른 액세스에서 기본을 클릭한 후 소유자를 클릭합니다.

  6. 계속을 클릭합니다.
  7. 완료를 클릭하여 서비스 계정 만들기를 마칩니다.

    브라우저 창을 닫지 마세요. 다음 단계에서 사용합니다.

서비스 계정 키 만들기

  1. Cloud Console에서 만든 서비스 계정의 이메일 주소를 클릭합니다.
  2. 를 클릭합니다.
  3. 키 추가를 클릭한 후 새 키 만들기를 클릭합니다.
  4. 만들기를 클릭합니다. JSON 키 파일이 컴퓨터에 다운로드됩니다.
  5. 닫기를 클릭합니다.

명령줄

로컬 머신 또는 Cloud Shell에서 Cloud SDK를 사용하여 다음 명령어를 실행할 수 있습니다.

  1. 서비스 계정을 만듭니다. NAME을 서비스 계정 이름으로 바꿉니다.

    gcloud iam service-accounts create NAME
  2. 서비스 계정에 권한을 부여합니다. PROJECT_ID를 프로젝트 ID로 바꿉니다.

    gcloud projects add-iam-policy-binding PROJECT_ID --member="serviceAccount:NAME@PROJECT_ID.iam.gserviceaccount.com" --role="roles/owner"
  3. 키 파일을 생성합니다. FILE_NAME을 키 파일 이름으로 바꿉니다.

    gcloud iam service-accounts keys create FILE_NAME.json --iam-account=NAME@PROJECT_ID.iam.gserviceaccount.com

환경 변수를 통해 사용자 인증 정보 전달

GOOGLE_APPLICATION_CREDENTIALS 환경 변수를 설정하여 애플리케이션 코드에 사용자 인증 정보를 제공합니다. 이 변수는 현재 셸 세션에만 적용되므로 새 세션을 연 경우 변수를 다시 설정합니다.

Linux 또는 macOS

export GOOGLE_APPLICATION_CREDENTIALS="KEY_PATH"

KEY_PATH를 서비스 계정 키가 포함된 JSON 파일의 경로로 바꿉니다.

예를 들면 다음과 같습니다.

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="KEY_PATH"

KEY_PATH를 서비스 계정 키가 포함된 JSON 파일의 경로로 바꿉니다.

예를 들면 다음과 같습니다.

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

명령어 프롬프트:

set GOOGLE_APPLICATION_CREDENTIALS=KEY_PATH

KEY_PATH를 서비스 계정 키가 포함된 JSON 파일의 경로로 바꿉니다.

위의 단계를 완료하면 위 섹션에 설명된 대로 ADC가 사용자 인증 정보를 자동으로 찾을 수 있습니다. ADC를 사용하면 더 적은 코드를 요구하고 다양한 환경에서 코드를 이동할 수 있으므로 이를 사용하는 것이 좋습니다.

코드를 사용하여 사용자 인증 정보 전달

또는 다음 예시와 같이 코드에서 서비스 계정 파일을 명시적으로 가리킬 수 있습니다. 다음 예시를 실행하려면 Cloud Storage 클라이언트 라이브러리를 설치해야 합니다.

C#

        // Some APIs, like Storage, accept a credential in their Create()
        // method.
        public object AuthExplicit(string projectId, string jsonPath)
        {
            // Explicitly use service account credentials by specifying
            // the private key file.
            var credential = GoogleCredential.FromFile(jsonPath);
            var storage = StorageClient.Create(credential);
            // Make an authenticated API request.
            var buckets = storage.ListBuckets(projectId);
            foreach (var bucket in buckets)
            {
                Console.WriteLine(bucket.Name);
            }
            return null;
        }
        // Other APIs, like Language, accept a channel in their Create()
        // method.
        public object AuthExplicit(string projectId, string jsonPath)
        {
            LanguageServiceClientBuilder builder = new LanguageServiceClientBuilder
            {
                CredentialsPath = jsonPath
            };

            LanguageServiceClient client = builder.Build();
            AnalyzeSentiment(client);
            return 0;
        }

Go


// explicit reads credentials from the specified path.
func explicit(jsonPath, projectID string) {
	ctx := context.Background()
	client, err := storage.NewClient(ctx, option.WithCredentialsFile(jsonPath))
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()
	fmt.Println("Buckets:")
	it := client.Buckets(ctx, projectID)
	for {
		battrs, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(battrs.Name)
	}
}

자바

static void authExplicit(String jsonPath) throws IOException {
  // You can specify a credential file by providing a path to GoogleCredentials.
  // Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment variable.
  GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(jsonPath))
        .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
  Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();

  System.out.println("Buckets:");
  Page<Bucket> buckets = storage.list();
  for (Bucket bucket : buckets.iterateAll()) {
    System.out.println(bucket.toString());
  }
}

Node.js

// Imports the Google Cloud client library.
const {Storage} = require('@google-cloud/storage');

// Instantiates a client. Explicitly use service account credentials by
// specifying the private key file. All clients in google-cloud-node have this
// helper, see https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/docs/authentication.md
// const projectId = 'project-id'
// const keyFilename = '/path/to/keyfile.json'
const storage = new Storage({projectId, keyFilename});

// Makes an authenticated API request.
async function listBuckets() {
  try {
    const [buckets] = await storage.getBuckets();

    console.log('Buckets:');
    buckets.forEach(bucket => {
      console.log(bucket.name);
    });
  } catch (err) {
    console.error('ERROR:', err);
  }
}
listBuckets();

PHP

namespace Google\Cloud\Samples\Auth;

// Imports the Cloud Storage client library.
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit($projectId, $serviceAccountPath)
{
    # Explicitly use service account credentials by specifying the private key
    # file.
    $config = [
        'keyFilePath' => $serviceAccountPath,
        'projectId' => $projectId,
    ];
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python

def explicit():
    from google.cloud import storage

    # Explicitly use service account credentials by specifying the private key
    # file.
    storage_client = storage.Client.from_service_account_json(
        'service_account.json')

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

# project_id = "Your Google Cloud project ID"
# key_file   = "path/to/service-account.json"
require "google/cloud/storage"

# Explicitly use service account credentials by specifying the private key
# file.
storage = Google::Cloud::Storage.new project: project_id, keyfile: key_file

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

사용자 인증 정보 관리 권장사항

사용자 인증 정보는 민감한 정보에 액세스할 수 있는 권한을 제공합니다. 다음 방법은 사용자 인증 정보에 대한 액세스를 보호하는 데 유용합니다.

  • API 키, OAuth 토큰, 서비스 계정 키와 같은 인증과 관련된 보안 비밀을 소스 코드에 삽입하지 마세요. Cloud Key Management Service와 같은 애플리케이션 소스 코드 외부의 사용자 인증 정보를 가리키는 환경 변수를 사용할 수 있습니다.

  • 테스트 환경 및 프로덕션 환경과 같이 각기 다른 컨텍스트에서 서로 다른 사용자 인증 정보를 만들고 사용하세요.

  • 제3자가 사용자 인증 정보를 가로채지 못하도록 HTTPS와 같은 보안 채널을 통해서만 사용자 인증 정보를 전송하세요. 일반 텍스트로 또는 URL의 일부로 전송하지 마세요.

  • 장시간 사용된 사용자 인증 정보를 클라이언트 측 애플리케이션에 삽입하지 마세요. 예를 들어 모바일 앱에 서비스 계정 키를 삽입하지 마세요. 제3자가 클라이언트 측 앱을 검사할 수 있으며 이 경우 손쉽게 사용자 인증 정보를 찾아 사용할 수 있습니다.

  • 더 이상 필요 없는 토큰을 취소합니다.

API 오류 문제 해결

Cloud APIs 오류에서 실패한 API 요청 문제를 해결하는 방법을 알아보세요.

다음 단계

직접 사용해 보기

Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.

무료로 시작하기