-
Notifications
You must be signed in to change notification settings - Fork 132
feat: default authentication support for external hosts #3655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
180e128
61ee038
004cea2
e65c555
2aa18db
c33ae1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,8 @@ | |
import com.google.api.gax.tracing.ApiTracerFactory; | ||
import com.google.api.gax.tracing.BaseApiTracerFactory; | ||
import com.google.api.gax.tracing.OpencensusTracerFactory; | ||
import com.google.auth.oauth2.AccessToken; | ||
import com.google.auth.oauth2.GoogleCredentials; | ||
import com.google.cloud.NoCredentials; | ||
import com.google.cloud.ServiceDefaults; | ||
import com.google.cloud.ServiceOptions; | ||
|
@@ -79,8 +81,11 @@ | |
import java.io.IOException; | ||
import java.net.MalformedURLException; | ||
import java.net.URL; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
import java.time.Duration; | ||
import java.util.ArrayList; | ||
import java.util.Base64; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
@@ -92,6 +97,7 @@ | |
import java.util.concurrent.ThreadFactory; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import java.util.regex.Pattern; | ||
import javax.annotation.Nonnull; | ||
import javax.annotation.Nullable; | ||
import javax.annotation.concurrent.GuardedBy; | ||
|
@@ -110,6 +116,11 @@ public class SpannerOptions extends ServiceOptions<Spanner, SpannerOptions> { | |
|
||
private static final String API_SHORT_NAME = "Spanner"; | ||
private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; | ||
private static final String CLOUD_SPANNER_HOST_FORMAT = ".*\\.googleapis\\.com.*"; | ||
|
||
@VisibleForTesting | ||
static final Pattern CLOUD_SPANNER_HOST_PATTERN = Pattern.compile(CLOUD_SPANNER_HOST_FORMAT); | ||
|
||
private static final ImmutableSet<String> SCOPES = | ||
ImmutableSet.of( | ||
"https://www.googleapis.com/auth/spanner.admin", | ||
|
@@ -799,6 +810,18 @@ protected SpannerOptions(Builder builder) { | |
enableBuiltInMetrics = builder.enableBuiltInMetrics; | ||
enableEndToEndTracing = builder.enableEndToEndTracing; | ||
monitoringHost = builder.monitoringHost; | ||
String externalHostTokenPath = System.getenv("SPANNER_EXTERNAL_HOST_AUTH_TOKEN"); | ||
if (builder.isExternalHost && builder.emulatorHost == null && externalHostTokenPath != null) { | ||
String token; | ||
try { | ||
token = | ||
Base64.getEncoder() | ||
.encodeToString(Files.readAllBytes(Paths.get(externalHostTokenPath))); | ||
} catch (IOException e) { | ||
throw SpannerExceptionFactory.newSpannerException(e); | ||
} | ||
credentials = new GoogleCredentials(new AccessToken(token, null)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This constructor is deprecated. Use the static There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
} | ||
} | ||
|
||
/** | ||
|
@@ -967,6 +990,7 @@ public static class Builder | |
private boolean enableBuiltInMetrics = SpannerOptions.environment.isEnableBuiltInMetrics(); | ||
private String monitoringHost = SpannerOptions.environment.getMonitoringHost(); | ||
private SslContext mTLSContext = null; | ||
private boolean isExternalHost = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this a method instead of a field. This now gives the impression of being in sync with the current settings, but it isn't if you do weird stuff (like first setting an emulator host and then overriding that by setting a host). By implementing it as a method, you can just calculate it based on the values at that time, instead of trying to set the correct value when setHost / setEmulatorHost is being set. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed the need to check emulatorHost. But had to keep isExternalHost calculation in setHost. Can't convert it to a method to do a on demand calculation since host is a private member in the parent builder class |
||
|
||
private static String createCustomClientLibToken(String token) { | ||
return token + " " + ServiceOptions.getGoogApiClientLibName(); | ||
|
@@ -1459,6 +1483,9 @@ public Builder setDecodeMode(DecodeMode decodeMode) { | |
@Override | ||
public Builder setHost(String host) { | ||
super.setHost(host); | ||
if (this.emulatorHost == null && !CLOUD_SPANNER_HOST_PATTERN.matcher(host).matches()) { | ||
this.isExternalHost = true; | ||
} | ||
// Setting a host should override any SPANNER_EMULATOR_HOST setting. | ||
setEmulatorHost(null); | ||
return this; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -407,6 +407,9 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) { | |
if (options.getConfigurator() != null) { | ||
options.getConfigurator().configure(builder); | ||
} | ||
if (options.usesEmulator()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||
builder.setEmulatorHost(key.host); | ||
} | ||
return builder.build().getService(); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!Strings.isNullOrEmpty(externalHostTokenPath)
over a null check.&& builder.credentials == null
to prevent the default credentials to override specific credentials that have been set for this builder.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
#3656