| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -532,6 +532,16 @@ | |||
| 532 | 532 | <version>2.94.0-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-trace-v1:current} --> | |
| 533 | 533 | <scope>test</scope> | |
| 534 | 534 | </dependency> | |
| 535 | + <dependency> | ||
| 536 | + <groupId>org.bouncycastle</groupId> | ||
| 537 | + <artifactId>bcprov-jdk18on</artifactId> | ||
| 538 | + <version>1.78</version> | ||
| 539 | + </dependency> | ||
| 540 | + <dependency> | ||
| 541 | + <groupId>com.google.crypto.tink</groupId> | ||
| 542 | + <artifactId>tink</artifactId> | ||
| 543 | + <version>1.13.0</version> | ||
| 544 | + </dependency> | ||
| 535 | 545 | </dependencies> | |
| 536 | 546 | <profiles> | |
| 537 | 547 | <profile> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -53,6 +53,7 @@ | |||
| 53 | 53 | import com.google.cloud.spanner.admin.database.v1.stub.DatabaseAdminStubSettings; | |
| 54 | 54 | import com.google.cloud.spanner.admin.instance.v1.InstanceAdminSettings; | |
| 55 | 55 | import com.google.cloud.spanner.admin.instance.v1.stub.InstanceAdminStubSettings; | |
| 56 | + import com.google.cloud.spanner.omni.SpannerOmniCredentials; | ||
| 56 | 57 | import com.google.cloud.spanner.spi.SpannerRpcFactory; | |
| 57 | 58 | import com.google.cloud.spanner.spi.v1.ChannelEndpointCacheFactory; | |
| 58 | 59 | import com.google.cloud.spanner.spi.v1.GapicSpannerRpc; | |
@@ -66,6 +67,7 @@ | |||
| 66 | 67 | import com.google.common.collect.ImmutableMap; | |
| 67 | 68 | import com.google.common.collect.ImmutableSet; | |
| 68 | 69 | import com.google.common.util.concurrent.ThreadFactoryBuilder; | |
| 70 | + import com.google.crypto.tink.util.SecretBytes; | ||
| 69 | 71 | import com.google.spanner.v1.DirectedReadOptions; | |
| 70 | 72 | import com.google.spanner.v1.ExecuteSqlRequest; | |
| 71 | 73 | import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; | |
@@ -1239,9 +1241,20 @@ private static Builder prepareBuilder(Builder builder) { | |||
| 1239 | 1241 | builder.sessionPoolOptions = | |
| 1240 | 1242 | builder.sessionPoolOptions.toBuilder().setExperimentalHost().build(); | |
| 1241 | 1243 | } | |
| 1242 | - if (builder.credentials == null) { | ||
| 1244 | + if (builder.username != null && builder.secretBytes != null) { | ||
| 1245 | + builder.setCredentials( | ||
| 1246 | + new SpannerOmniCredentials(builder.username, builder.secretBytes, builder.host)); | ||
| 1247 | + } else if (builder.credentials == null) { | ||
| 1243 | 1248 | builder.setCredentials(environment.getDefaultSpannerOmniCredentials()); | |
| 1244 | 1249 | } | |
| 1250 | + if (builder.credentials instanceof SpannerOmniCredentials) { | ||
| 1251 | + ((SpannerOmniCredentials) builder.credentials) | ||
| 1252 | + .initChannel(builder.usePlainText, builder.mTLSContext); | ||
| 1253 | + } | ||
| 1254 | + } else { | ||
| 1255 | + if (builder.username != null || builder.secretBytes != null) { | ||
| 1256 | + throw new IllegalStateException("login() can only be used with InstanceType.OMNI."); | ||
| 1257 | + } | ||
| 1245 | 1258 | } | |
| 1246 | 1259 | return builder; | |
| 1247 | 1260 | } | |
@@ -1296,6 +1309,8 @@ private static Builder prepareBuilder(Builder builder) { | |||
| 1296 | 1309 | DEFAULT_ADMIN_REQUESTS_LIMIT_EXCEEDED_RETRY_SETTINGS; | |
| 1297 | 1310 | private boolean autoThrottleAdministrativeRequests = false; | |
| 1298 | 1311 | private boolean trackTransactionStarter = false; | |
| 1312 | + private String username; | ||
| 1313 | + private SecretBytes secretBytes; | ||
| 1299 | 1314 | private Map<DatabaseId, QueryOptions> defaultQueryOptions = new HashMap<>(); | |
| 1300 | 1315 | private boolean enableGrpcGcpOtelMetrics = | |
| 1301 | 1316 | SpannerOptions.environment.isEnableGrpcGcpOtelMetrics(); | |
@@ -1910,6 +1925,28 @@ public Builder setType(InstanceType instanceType) { | |||
| 1910 | 1925 | return this; | |
| 1911 | 1926 | } | |
| 1912 | 1927 | ||
| 1928 | + /** | ||
| 1929 | + * Authenticates to Spanner Omni using the provided username and password, and configures the | ||
| 1930 | + * resulting token for use in subsequent Spanner API calls. | ||
| 1931 | + * | ||
| 1932 | + * <p>Note: The provided {@code password} array will be cleared (zeroed out) by this method for | ||
| 1933 | + * security purposes. | ||
| 1934 | + * | ||
| 1935 | + * @param username The username for login. | ||
| 1936 | + * @param password The password for login. | ||
| 1937 | + * @return this builder | ||
| 1938 | + */ | ||
| 1939 | + public Builder login(String username, char[] password) { | ||
| 1940 | + Preconditions.checkArgument( | ||
| 1941 | + username != null && !username.isEmpty(), "username cannot be null or empty"); | ||
| 1942 | + Preconditions.checkArgument( | ||
| 1943 | + password != null && password.length > 0, "password cannot be null or empty"); | ||
| 1944 | + | ||
| 1945 | + this.username = username; | ||
| 1946 | + this.secretBytes = SpannerOmniCredentials.convertToSecretBytes(password); | ||
| 1947 | + return this; | ||
| 1948 | + } | ||
| 1949 | + | ||
| 1913 | 1950 | /** Enables gRPC-GCP extension with the default settings. This option is enabled by default. */ | |
| 1914 | 1951 | public Builder enableGrpcGcpExtension() { | |
| 1915 | 1952 | return this.enableGrpcGcpExtension(null); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -89,12 +89,14 @@ | |||
| 89 | 89 | import com.google.cloud.spanner.SpannerOptions; | |
| 90 | 90 | import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.GrpcInterceptorProviderConverter; | |
| 91 | 91 | import com.google.cloud.spanner.connection.StatementExecutor.StatementExecutorType; | |
| 92 | + import com.google.cloud.spanner.omni.SpannerOmniCredentials; | ||
| 92 | 93 | import com.google.common.annotations.VisibleForTesting; | |
| 93 | 94 | import com.google.common.base.MoreObjects; | |
| 94 | 95 | import com.google.common.base.Preconditions; | |
| 95 | 96 | import com.google.common.base.Strings; | |
| 96 | 97 | import com.google.common.base.Suppliers; | |
| 97 | 98 | import com.google.common.collect.ImmutableMap; | |
| 99 | + import com.google.crypto.tink.util.SecretBytes; | ||
| 98 | 100 | import io.grpc.Deadline; | |
| 99 | 101 | import io.grpc.Deadline.Ticker; | |
| 100 | 102 | import io.opentelemetry.api.OpenTelemetry; | |
@@ -154,6 +156,8 @@ public class ConnectionOptions { | |||
| 154 | 156 | static final boolean DEFAULT_USE_PLAIN_TEXT = false; | |
| 155 | 157 | static final boolean DEFAULT_IS_EXPERIMENTAL_HOST = false; | |
| 156 | 158 | static final SpannerOptions.InstanceType DEFAULT_TYPE = SpannerOptions.InstanceType.CLOUD; | |
| 159 | + static final String DEFAULT_USERNAME = ""; | ||
| 160 | + static final String DEFAULT_PASSWORD = ""; | ||
| 157 | 161 | static final boolean DEFAULT_AUTOCOMMIT = true; | |
| 158 | 162 | static final boolean DEFAULT_READONLY = false; | |
| 159 | 163 | static final boolean DEFAULT_RETRY_ABORTS_INTERNALLY = true; | |
@@ -224,6 +228,12 @@ public class ConnectionOptions { | |||
| 224 | 228 | /** The type of Spanner instance to connect to (cloud, omni, or emulator). */ | |
| 225 | 229 | public static final String TYPE_PROPERTY_NAME = "type"; | |
| 226 | 230 | ||
| 231 | + /** Username for OPAQUE login */ | ||
| 232 | + public static final String USERNAME_PROPERTY_NAME = "username"; | ||
| 233 | + | ||
| 234 | + /** Password for OPAQUE login */ | ||
| 235 | + public static final String PASSWORD_PROPERTY_NAME = "password"; | ||
| 236 | + | ||
| 227 | 237 | /** Client certificate path to establish mTLS */ | |
| 228 | 238 | static final String CLIENT_CERTIFICATE_PROPERTY_NAME = "clientCertificate"; | |
| 229 | 239 | ||
@@ -775,6 +785,8 @@ private ConnectionOptions(Builder builder) { | |||
| 775 | 785 | System.getenv()); | |
| 776 | 786 | GoogleCredentials defaultSpannerOmniCredentials = | |
| 777 | 787 | SpannerOptions.getDefaultSpannerOmniCredentialsFromSysEnv(); | |
| 788 | + String username = getInitialConnectionPropertyValue(ConnectionProperties.USERNAME); | ||
| 789 | + String password = getInitialConnectionPropertyValue(ConnectionProperties.PASSWORD); | ||
| 778 | 790 | // Using credentials on a plain text connection is not allowed, so if the user has not specified | |
| 779 | 791 | // any credentials and is using a plain text connection, we should not try to get the | |
| 780 | 792 | // credentials from the environment, but default to NoCredentials. | |
@@ -783,12 +795,18 @@ && getInitialConnectionPropertyValue(CREDENTIALS_URL) == null | |||
| 783 | 795 | && getInitialConnectionPropertyValue(ENCODED_CREDENTIALS) == null | |
| 784 | 796 | && getInitialConnectionPropertyValue(CREDENTIALS_PROVIDER) == null | |
| 785 | 797 | && getInitialConnectionPropertyValue(OAUTH_TOKEN) == null | |
| 798 | + && Strings.isNullOrEmpty(getInitialConnectionPropertyValue(ConnectionProperties.USERNAME)) | ||
| 786 | 799 | && usePlainText) { | |
| 787 | 800 | this.credentials = NoCredentials.getInstance(); | |
| 788 | 801 | } else if (getInitialConnectionPropertyValue(OAUTH_TOKEN) != null) { | |
| 789 | 802 | this.credentials = | |
| 790 | 803 | new GoogleCredentials( | |
| 791 | 804 | new AccessToken(getInitialConnectionPropertyValue(OAUTH_TOKEN), null)); | |
| 805 | + } else if ((isSpannerOmniPattern || isSpannerOmni()) | ||
| 806 | + && !Strings.isNullOrEmpty(username) | ||
| 807 | + && !Strings.isNullOrEmpty(password)) { | ||
| 808 | + SecretBytes secretBytes = SpannerOmniCredentials.convertToSecretBytes(password.toCharArray()); | ||
| 809 | + this.credentials = new SpannerOmniCredentials(username, secretBytes, this.host); | ||
| 792 | 810 | } else if ((isSpannerOmniPattern || isSpannerOmni()) && defaultSpannerOmniCredentials != null) { | |
| 793 | 811 | this.credentials = defaultSpannerOmniCredentials; | |
| 794 | 812 | } else if (getInitialConnectionPropertyValue(CREDENTIALS_PROVIDER) != null) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -279,6 +279,20 @@ public class ConnectionProperties { | |||
| 279 | 279 | }, | |
| 280 | 280 | InstanceTypeConverter.INSTANCE, | |
| 281 | 281 | Context.STARTUP); | |
| 282 | + static final ConnectionProperty<String> USERNAME = | ||
| 283 | + create( | ||
| 284 | + ConnectionOptions.USERNAME_PROPERTY_NAME, | ||
| 285 | + "The username to use for OPAQUE login.", | ||
| 286 | + ConnectionOptions.DEFAULT_USERNAME, | ||
| 287 | + StringValueConverter.INSTANCE, | ||
| 288 | + Context.STARTUP); | ||
| 289 | + static final ConnectionProperty<String> PASSWORD = | ||
| 290 | + create( | ||
| 291 | + ConnectionOptions.PASSWORD_PROPERTY_NAME, | ||
| 292 | + "The password to use for OPAQUE login.", | ||
| 293 | + ConnectionOptions.DEFAULT_PASSWORD, | ||
| 294 | + StringValueConverter.INSTANCE, | ||
| 295 | + Context.STARTUP); | ||
| 282 | 296 | static final ConnectionProperty<String> CLIENT_CERTIFICATE = | |
| 283 | 297 | create( | |
| 284 | 298 | CLIENT_CERTIFICATE_PROPERTY_NAME, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments