Java tutorial
/* * Copyright (C) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.cloud.dataflow.sdk.util; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AbstractPromptReceiver; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.auth.oauth2.GoogleOAuthConstants; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.client.util.store.FileDataStoreFactory; import com.google.cloud.dataflow.sdk.options.GcpOptions; import com.google.common.base.Preconditions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Provides support for loading credentials. */ public class Credentials { private static final Logger LOG = LoggerFactory.getLogger(Credentials.class); /** * OAuth 2.0 scopes used by a local worker (not on GCE). * The scope cloud-platform provides access to all Cloud Platform resources. * cloud-platform isn't sufficient yet for talking to datastore so we request * those resources separately. * * <p>Note that trusted scope relationships don't apply to OAuth tokens, so for * services we access directly (GCS) as opposed to through the backend * (BigQuery, GCE), we need to explicitly request that scope. */ private static final List<String> SCOPES = Arrays.asList("https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/devstorage.full_control", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/datastore"); private static class PromptReceiver extends AbstractPromptReceiver { @Override public String getRedirectUri() { return GoogleOAuthConstants.OOB_REDIRECT_URI; } } /** * Initializes OAuth2 credentials. * * <p>This can use 3 different mechanisms for obtaining a credential: * <ol> * <li> * It can fetch the * <a href="https://developers.google.com/accounts/docs/application-default-credentials"> * application default credentials</a>. * </li> * <li> * The user can specify a client secrets file and go through the OAuth2 * webflow. The credential will then be cached in the user's home * directory for reuse. Provide the property "secrets_file" to use this * mechanism. * </li> * <li> * The user can specify a file containing a service account. * Provide the properties "service_account_keyfile" and * "service_account_name" to use this mechanism. * </li> * </ol> * The default mechanism is to use the * <a href="https://developers.google.com/accounts/docs/application-default-credentials"> * application default credentials</a>. The other options can be used by providing the * corresponding properties. */ public static Credential getCredential(GcpOptions options) throws IOException, GeneralSecurityException { String keyFile = options.getServiceAccountKeyfile(); String accountName = options.getServiceAccountName(); if (keyFile != null && accountName != null) { try { return getCredentialFromFile(keyFile, accountName, SCOPES); } catch (GeneralSecurityException e) { throw new IOException("Unable to obtain credentials from file", e); } } if (options.getSecretsFile() != null) { return getCredentialFromClientSecrets(options, SCOPES); } try { return GoogleCredential.getApplicationDefault().createScoped(SCOPES); } catch (IOException e) { throw new RuntimeException("Unable to get application default credentials. Please see " + "https://developers.google.com/accounts/docs/application-default-credentials " + "for details on how to specify credentials. This version of the SDK is " + "dependent on the gcloud core component version 2015.02.05 or newer to " + "be able to get credentials from the currently authorized user via gcloud auth.", e); } } /** * Loads OAuth2 credential from a local file. */ private static Credential getCredentialFromFile(String keyFile, String accountId, Collection<String> scopes) throws IOException, GeneralSecurityException { GoogleCredential credential = new GoogleCredential.Builder().setTransport(Transport.getTransport()) .setJsonFactory(Transport.getJsonFactory()).setServiceAccountId(accountId) .setServiceAccountScopes(scopes).setServiceAccountPrivateKeyFromP12File(new File(keyFile)).build(); LOG.info("Created credential from file {}", keyFile); return credential; } /** * Loads OAuth2 credential from client secrets, which may require an * interactive authorization prompt. */ private static Credential getCredentialFromClientSecrets(GcpOptions options, Collection<String> scopes) throws IOException, GeneralSecurityException { String clientSecretsFile = options.getSecretsFile(); Preconditions.checkArgument(clientSecretsFile != null); HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); GoogleClientSecrets clientSecrets; try { clientSecrets = GoogleClientSecrets.load(jsonFactory, new FileReader(clientSecretsFile)); } catch (IOException e) { throw new RuntimeException("Could not read the client secrets from file: " + clientSecretsFile, e); } FileDataStoreFactory dataStoreFactory = new FileDataStoreFactory( new java.io.File(options.getCredentialDir())); GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, clientSecrets, scopes).setDataStoreFactory(dataStoreFactory) .setTokenServerUrl(new GenericUrl(options.getTokenServerUrl())) .setAuthorizationServerEncodedUrl(options.getAuthorizationServerEncodedUrl()).build(); // The credentialId identifies the credential if we're using a persistent // credential store. Credential credential = new AuthorizationCodeInstalledApp(flow, new PromptReceiver()) .authorize(options.getCredentialId()); LOG.info("Got credential from client secret"); return credential; } }