├── .dockerignore
├── .gitignore
├── CHANGES.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── VERSION
├── code
├── authorizer
│ ├── Dockerfile
│ ├── install.sh
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── google
│ │ │ │ └── cloud
│ │ │ │ └── broker
│ │ │ │ └── apps
│ │ │ │ └── authorizer
│ │ │ │ └── Authorizer.java
│ │ └── resources
│ │ │ ├── index.soy
│ │ │ ├── reference.conf
│ │ │ ├── server_error.soy
│ │ │ └── success.soy
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ └── apps
│ │ └── authorizer
│ │ ├── AuthorizerTest.java
│ │ └── TemplateTest.java
├── broker-server
│ ├── Dockerfile
│ ├── descriptor.xml
│ ├── install-dev.sh
│ ├── install.sh
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── google
│ │ │ │ └── cloud
│ │ │ │ └── broker
│ │ │ │ └── apps
│ │ │ │ └── brokerserver
│ │ │ │ ├── BrokerServer.java
│ │ │ │ ├── ClientAddressServerInterceptor.java
│ │ │ │ ├── accesstokens
│ │ │ │ ├── AccessBoundaryUtils.java
│ │ │ │ ├── AccessToken.java
│ │ │ │ ├── AccessTokenCacheFetcher.java
│ │ │ │ └── providers
│ │ │ │ │ ├── AbstractProvider.java
│ │ │ │ │ ├── AbstractUserProvider.java
│ │ │ │ │ ├── DomainWideDelegationAuthorityProvider.java
│ │ │ │ │ ├── HybridProvider.java
│ │ │ │ │ ├── RefreshTokenProvider.java
│ │ │ │ │ ├── RevokeRefreshTokens.java
│ │ │ │ │ ├── ServiceAccountProvider.java
│ │ │ │ │ └── experimental
│ │ │ │ │ └── JSONFileCredentialsProvider.java
│ │ │ │ ├── endpoints
│ │ │ │ ├── CancelSessionToken.java
│ │ │ │ ├── GetAccessToken.java
│ │ │ │ ├── GetSessionToken.java
│ │ │ │ └── RenewSessionToken.java
│ │ │ │ ├── logging
│ │ │ │ ├── CustomJsonLayout.java
│ │ │ │ └── LoggingUtils.java
│ │ │ │ ├── sessions
│ │ │ │ ├── Session.java
│ │ │ │ ├── SessionAuthenticator.java
│ │ │ │ ├── SessionCacheFetcher.java
│ │ │ │ ├── SessionCleanup.java
│ │ │ │ ├── SessionToken.java
│ │ │ │ └── SessionTokenUtils.java
│ │ │ │ └── validation
│ │ │ │ ├── GrpcRequestValidation.java
│ │ │ │ ├── ProxyUserValidation.java
│ │ │ │ └── ScopeValidation.java
│ │ ├── proto
│ │ │ └── broker.proto
│ │ └── resources
│ │ │ ├── logback.xml
│ │ │ └── reference.conf
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ ├── apps
│ │ └── brokerserver
│ │ │ ├── BrokerServerTest.java
│ │ │ ├── accesstokens
│ │ │ ├── AccessBoundaryUtilsTest.java
│ │ │ ├── AccessTokenCacheFetcherTest.java
│ │ │ ├── MockAccessBoundary.java
│ │ │ └── providers
│ │ │ │ ├── AbstractProviderTest.java
│ │ │ │ ├── DomainWideDelegationAuthorityProviderTest.java
│ │ │ │ ├── HybridProviderTest.java
│ │ │ │ ├── MockProvider.java
│ │ │ │ ├── RefreshTokenProviderTest.java
│ │ │ │ └── ServiceAccountProviderTest.java
│ │ │ ├── sessions
│ │ │ ├── SessionCacheFetcherTest.java
│ │ │ └── SessionTest.java
│ │ │ └── validation
│ │ │ ├── ProxyUserValidationTest.java
│ │ │ └── ValidationTest.java
│ │ ├── authentication
│ │ └── backends
│ │ │ └── MockAuthenticator.java
│ │ └── usermapping
│ │ └── MockUserMapper.java
├── client
│ ├── client-lib
│ │ ├── pom.xml
│ │ └── src
│ │ │ └── main
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── google
│ │ │ │ └── cloud
│ │ │ │ └── broker
│ │ │ │ └── client
│ │ │ │ ├── connect
│ │ │ │ ├── BrokerGateway.java
│ │ │ │ └── BrokerServerInfo.java
│ │ │ │ ├── credentials
│ │ │ │ ├── BrokerBaseCredentials.java
│ │ │ │ ├── BrokerKerberosCredentials.java
│ │ │ │ └── BrokerSessionCredentials.java
│ │ │ │ ├── endpoints
│ │ │ │ ├── CancelSessionToken.java
│ │ │ │ ├── GetAccessToken.java
│ │ │ │ ├── GetSessionToken.java
│ │ │ │ └── RenewSessionToken.java
│ │ │ │ └── utils
│ │ │ │ ├── GrpcUtils.java
│ │ │ │ ├── OAuthUtils.java
│ │ │ │ └── SpnegoUtils.java
│ │ │ └── proto
│ │ │ └── broker.proto
│ └── hadoop-connector
│ │ ├── pom.xml
│ │ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── google
│ │ │ │ └── cloud
│ │ │ │ └── broker
│ │ │ │ └── client
│ │ │ │ └── hadoop
│ │ │ │ └── fs
│ │ │ │ ├── BrokerAccessTokenProvider.java
│ │ │ │ ├── BrokerDelegationTokenBinding.java
│ │ │ │ ├── BrokerTokenIdentifier.java
│ │ │ │ ├── BrokerTokenRenewer.java
│ │ │ │ ├── Utils.java
│ │ │ │ └── commands
│ │ │ │ ├── CancelSessionToken.java
│ │ │ │ ├── CommandUtils.java
│ │ │ │ ├── GetAccessToken.java
│ │ │ │ ├── GetSessionToken.java
│ │ │ │ ├── PingServer.java
│ │ │ │ └── RenewSessionToken.java
│ │ └── resources
│ │ │ └── META-INF
│ │ │ └── services
│ │ │ ├── org.apache.hadoop.security.token.TokenIdentifier
│ │ │ └── org.apache.hadoop.security.token.TokenRenewer
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ └── client
│ │ ├── hadoop
│ │ └── fs
│ │ │ ├── BrokerAccessTokenProviderTest.java
│ │ │ ├── BrokerDelegationTokenBindingTest.java
│ │ │ ├── BrokerTokenIdentifierTest.java
│ │ │ └── TestingTools.java
│ │ └── utils
│ │ ├── GrpcUtilsTest.java
│ │ └── SpnegoUtilsTest.java
├── core
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── google
│ │ │ └── cloud
│ │ │ └── broker
│ │ │ ├── authentication
│ │ │ ├── AuthorizationHeaderServerInterceptor.java
│ │ │ └── backends
│ │ │ │ ├── AbstractAuthenticationBackend.java
│ │ │ │ └── SpnegoAuthenticator.java
│ │ │ ├── caching
│ │ │ ├── CacheFetcher.java
│ │ │ ├── local
│ │ │ │ └── LocalCache.java
│ │ │ └── remote
│ │ │ │ ├── AbstractRemoteCache.java
│ │ │ │ └── DummyCache.java
│ │ │ ├── checks
│ │ │ ├── CheckResult.java
│ │ │ └── SystemCheck.java
│ │ │ ├── database
│ │ │ ├── DatabaseObjectNotFound.java
│ │ │ ├── InitializeDatabase.java
│ │ │ ├── backends
│ │ │ │ ├── AbstractDatabaseBackend.java
│ │ │ │ └── DummyDatabaseBackend.java
│ │ │ └── models
│ │ │ │ └── Model.java
│ │ │ ├── encryption
│ │ │ └── backends
│ │ │ │ ├── AbstractEncryptionBackend.java
│ │ │ │ └── DummyEncryptionBackend.java
│ │ │ ├── oauth
│ │ │ ├── OauthClientSecretsLoader.java
│ │ │ ├── RefreshToken.java
│ │ │ └── RefreshTokenUtils.java
│ │ │ ├── secretmanager
│ │ │ ├── DownloadSecrets.java
│ │ │ └── SecretManager.java
│ │ │ ├── settings
│ │ │ └── AppSettings.java
│ │ │ ├── usermapping
│ │ │ ├── AbstractUserMapper.java
│ │ │ ├── KerberosUserMapper.java
│ │ │ └── MapUser.java
│ │ │ ├── utils
│ │ │ ├── CloudStorageUtils.java
│ │ │ ├── Constants.java
│ │ │ ├── InstanceUtils.java
│ │ │ └── TimeUtils.java
│ │ │ └── validation
│ │ │ └── EmailValidation.java
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ ├── authentication
│ │ └── backends
│ │ │ ├── AbstractAuthenticationBackendTest.java
│ │ │ ├── FakeKDC.java
│ │ │ └── SpnegoAuthenticatorTest.java
│ │ ├── caching
│ │ └── remote
│ │ │ └── AbstractRemoteCacheTest.java
│ │ ├── database
│ │ └── backends
│ │ │ └── AbstractDatabaseBackendTest.java
│ │ ├── encryption
│ │ └── backends
│ │ │ └── AbstractEncryptionBackendTest.java
│ │ ├── oauth
│ │ └── RefreshTokenTest.java
│ │ ├── secretmanager
│ │ └── SecretManagerTest.java
│ │ ├── settings
│ │ └── SettingsOverride.java
│ │ └── usermapping
│ │ └── KerberosUserMapperTest.java
└── extensions
│ ├── caching
│ ├── cloud-datastore
│ │ ├── pom.xml
│ │ └── src
│ │ │ ├── main
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── google
│ │ │ │ └── cloud
│ │ │ │ └── broker
│ │ │ │ └── caching
│ │ │ │ └── remote
│ │ │ │ ├── CloudDatastoreCache.java
│ │ │ │ └── DatastoreCacheCleanup.java
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── google
│ │ │ └── cloud
│ │ │ └── broker
│ │ │ └── caching
│ │ │ └── remote
│ │ │ └── CloudDatastoreCacheTest.java
│ └── redis
│ │ ├── pom.xml
│ │ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── google
│ │ │ └── cloud
│ │ │ └── broker
│ │ │ └── caching
│ │ │ └── remote
│ │ │ └── RedisCache.java
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ └── caching
│ │ └── remote
│ │ └── RedisCacheTest.java
│ ├── database
│ ├── cloud-datastore
│ │ ├── pom.xml
│ │ └── src
│ │ │ ├── main
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── google
│ │ │ │ └── cloud
│ │ │ │ └── broker
│ │ │ │ └── database
│ │ │ │ └── backends
│ │ │ │ └── CloudDatastoreBackend.java
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── google
│ │ │ └── cloud
│ │ │ └── broker
│ │ │ └── database
│ │ │ └── backends
│ │ │ ├── CloudDatastoreBackendTest.java
│ │ │ └── Foo.java
│ └── jdbc
│ │ ├── pom.xml
│ │ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── google
│ │ │ └── cloud
│ │ │ └── broker
│ │ │ └── database
│ │ │ └── backends
│ │ │ └── JDBCBackend.java
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ └── database
│ │ └── backends
│ │ ├── JDBCBackendTest.java
│ │ ├── MariaDBBackendTest.java
│ │ ├── PostgreSQLBackendTest.java
│ │ └── SQLiteBackendTest.java
│ └── encryption
│ └── cloud-kms
│ ├── pom.xml
│ └── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── google
│ │ └── cloud
│ │ └── broker
│ │ └── encryption
│ │ ├── GenerateDEK.java
│ │ └── backends
│ │ ├── CloudKMSBackend.java
│ │ └── keyset
│ │ ├── CloudStorageKeysetManager.java
│ │ ├── FilesystemKeysetManager.java
│ │ ├── KeysetManager.java
│ │ └── KeysetUtils.java
│ └── test
│ └── java
│ └── com
│ └── google
│ └── cloud
│ └── broker
│ └── encryption
│ └── backends
│ └── CloudKMSBackendTest.java
├── docs
├── concepts
│ ├── authentication.md
│ ├── authorizer.md
│ ├── broker-server.md
│ ├── caching.md
│ ├── connector.md
│ ├── database.md
│ ├── encryption.md
│ ├── index.md
│ ├── logging.md
│ ├── providers.md
│ ├── secret-management.md
│ ├── sessions.md
│ ├── settings.md
│ ├── tls.md
│ └── user-mapping.md
├── contribute
│ ├── development.md
│ ├── index.md
│ ├── load-tests.md
│ └── regression-tests.md
├── deploy
│ └── index.md
├── img
│ ├── access-example-service-accounts.svg
│ ├── access-example-users.svg
│ ├── delegated-auth-architecture.svg
│ ├── delegated-auth-sequence.svg
│ ├── delegated-auth-sequence.txt
│ ├── demo-architecture.svg
│ ├── direct-auth-architecture.svg
│ ├── direct-auth-sequence.svg
│ ├── direct-auth-sequence.txt
│ ├── dwd-admin-screen.png
│ └── dwd-service-accounts-screen.png
├── index.md
└── tutorials
│ └── index.md
├── init-action
└── broker-hadoop-connector.sh
├── kubernetes
└── broker-server
│ └── templates
│ └── session-cleanup.yaml
├── load-testing
├── brokerservice
│ └── protobuf
│ │ └── broker.proto
├── client.py
├── install.sh
├── locustfile.py
└── settings.py.template
├── pom.xml
├── run.sh
└── terraform
├── broker.tf
├── client.tf
├── misc.tf
├── origin_kdc.tf
├── peering.tf
├── shadow.tf
├── startup-script-kdc.tpl
├── variables.tf
└── versions.tf
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | # Ignore all by default:
13 | *
14 |
15 | # Allowlist only the required assets:
16 | !/code/authorizer/install.sh
17 | !code/broker-server/install.sh
18 | !code/built-jars
19 | !code/authorizer/target/authorizer-*-jar-with-dependencies.jar
20 | !code/broker-server/target/broker-server-*-jar-with-dependencies.jar
21 | !code/extensions/caching/cloud-datastore/target/cache-backend-cloud-datastore-*-jar-with-dependencies.jar
22 | !code/extensions/caching/redis/target/cache-backend-redis-*-jar-with-dependencies.jar
23 | !code/extensions/database/jdbc/target/database-backend-jdbc-*-jar-with-dependencies.jar
24 | !code/extensions/database/cloud-datastore/target/database-backend-cloud-datastore-*-jar-with-dependencies.jar
25 | !code/extensions/encryption/cloud-kms/target/encryption-backend-cloud-kms-*-jar-with-dependencies.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | # Terraform artifacts:
13 | terraform/terraform.tfstate*
14 | terraform/.terraform*
15 | terraform/*.tfvars
16 |
17 | # Load testing artifacts
18 | load-testing/settings.py
19 | load-testing/brokerservice/protobuf/broker_pb2_grpc.py
20 | load-testing/brokerservice/protobuf/broker_pb2.py
21 |
22 | # Unit testing artifacts
23 | service-account-key.json
24 |
25 | # Custom deployment specific files
26 | deploy/**
27 |
28 | # Java artifacts
29 | *.jar
30 | **/target/**
31 | dependency-reduced-pom.xml
32 | code/built-jars
33 |
34 | # Redis artifacts
35 | dump.rdb
36 |
37 | # Secrets
38 | client_secret*.json
39 | *.keytab
40 | *.crt
41 | *.key
42 | *.csr
43 | *.pem
44 | dek.json
45 |
46 | # Ignore .DS_Store (folder metadata file in OS X)
47 | *.DS_Store
48 |
49 | # Ignore IDE specific files
50 | .idea
51 | *.iml
52 |
53 | # NodeJS
54 | npm-debug.log
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | Check out all the details in the [documentation](docs/contribute/index.md).
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GCP Token Broker
2 |
3 | ## About this project
4 |
5 | The GCP Token Broker enables end-to-end Kerberos security and Cloud IAM integration for Hadoop
6 | workloads on [Google Cloud Platform](https://cloud.google.com/) (GCP).
7 |
8 | This project aims to achieve the following goals:
9 |
10 | * Bridge the gap between Kerberos and Cloud IAM to allow users to log in with Kerberos and access GCP resources.
11 | * Enable multi-tenancy for Hadoop clusters on Compute Engine and Cloud Dataproc.
12 | * Enable user impersonation by Hadoop services such as Hive, Presto, or Oozie.
13 |
14 | This project also strives to address the following requirements, which many enterprise customers have when
15 | they're looking to migrate on-premise workloads to the cloud:
16 |
17 | * All access to GCP resources (Cloud Storage, Google BigQuery, Cloud Bigtable, etc) should be attributable
18 | to the individual users who initiated the requests.
19 | * No long-lived credentials should be stored on client machines or worker nodes.
20 | * Cause as few changes as possible to existing on-premise security systems and user workflows.
21 |
22 | ## Documentation
23 |
24 | See the full documentation [here](docs/index.md).
25 |
26 | ## Repository's contents
27 |
28 | This repository contains:
29 |
30 | - `apps`: Server applications, including:
31 | - `authorizer`: Web UI for the OAuth flow that users must go through to authorize the broker service.
32 | - `broker`: The broker service itself.
33 | - `deploy`: Helm charts for deploying the broker service and the authorizer app to a Kubernetes cluster.
34 | - `docs`: Technical documentation for this project.
35 | - `connector`: Extension for the GCS Connector to allow Hadoop to communicate with the broker.
36 | - `init-action`: Initialization action to install the broker dependencies in
37 | a Cloud Dataproc cluster.
38 | - `load-testing`: Scripts for running loads tests for the broker service.
39 | - `terraform`: Terraform scripts to deploy a sample demo environment. This is
40 | provided only as a reference and **_should not_** be used as-is in production.
41 |
42 | ## Roadmap
43 |
44 | Included in the current **early** release:
45 |
46 | * Full lifecycle of Hadoop-style delegation tokens: creation, renewal, cancellation.
47 | * Support for Hadoop-style proxy users.
48 | * Authentication backend: Kerberos.
49 | * Target GCP service: Cloud Storage.
50 | * Database backends: Cloud Datastore, JDBC.
51 | * Cache backend: Redis on Cloud Memorystore.
52 |
53 | Plans for the **stable** releases:
54 |
55 | * Performance optimizations.
56 | * API stabilization.
57 |
58 | Plans for **future** releases:
59 |
60 | * Target GCP services: BigQuery, Cloud Bigtable, Cloud PubSub.
61 | * Database backends: Cloud Firestore, Cloud Bigtable.
62 | * Cache backends: Memcached, Cloud Bigtable.
63 | * Support for more authentication backends: TBD.
64 |
65 | ## How to Contribute
66 |
67 | We'd love to accept your patches and contributions to this project. There are
68 | just a few small guidelines you need to follow. See the [contributing guide](docs/contribute/index.md)
69 | for more details.
70 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 0.10.5
--------------------------------------------------------------------------------
/code/authorizer/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | FROM ubuntu:18.04
13 |
14 | COPY ./code/authorizer/install.sh /base/code/authorizer/install.sh
15 |
16 | RUN /base/code/authorizer/install.sh
17 |
18 | COPY ./code/authorizer/target/authorizer-*-jar-with-dependencies.jar /classpath/authorizer.jar
19 | COPY ./code/extensions/database/jdbc/target/database-backend-jdbc-*-jar-with-dependencies.jar /classpath/database-backend-jdbc.jar
20 | COPY ./code/extensions/database/cloud-datastore/target/database-backend-cloud-datastore-*-jar-with-dependencies.jar /classpath/database-backend-cloud-datastore.jar
21 | COPY ./code/extensions/encryption/cloud-kms/target/encryption-backend-cloud-kms-*-jar-with-dependencies.jar /classpath/encryption-backend-cloud-kms.jar
22 |
23 | WORKDIR /base/code/authorizer
24 |
25 | ENTRYPOINT ["java", "-cp", "/classpath/*", "com.google.cloud.broker.apps.authorizer.Authorizer"]
--------------------------------------------------------------------------------
/code/authorizer/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Google LLC
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | apt-get update
15 |
16 | DEBIAN_FRONTEND=noninteractive apt-get install -y \
17 | krb5-user \
18 | libkrb5-dev \
19 | openjdk-11-jre-headless
--------------------------------------------------------------------------------
/code/authorizer/src/main/resources/index.soy:
--------------------------------------------------------------------------------
1 | /**
2 | Copyright 2020 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | {namespace Authorizer.Templates}
18 |
19 | {template .index}
20 | {@param GOOGLE_LOGIN_URI: string}
21 |
22 |
23 | GCP Token Broker
24 |
25 |
26 |
Welcome to the GCP Token Broker authorization page!
27 |
To authorize the broker, click this button then follow the log-in steps:
28 |
29 |
30 |
31 | {/template}
32 |
--------------------------------------------------------------------------------
/code/authorizer/src/main/resources/reference.conf:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | # Default values for some of the Authorizer settings
13 |
14 | authorizer {
15 | host = "0.0.0.0"
16 | port = 8080
17 | }
18 | logging {
19 | level = "INFO"
20 | }
21 | database {
22 | backend = "com.google.cloud.broker.database.backends.CloudDatastoreBackend"
23 | }
24 | encryption {
25 | backend = "com.google.cloud.broker.encryption.backends.CloudKMSBackend"
26 | }
27 | secret-manager {
28 | downloads = []
29 | }
30 | remote-cache.backend = "com.google.cloud.broker.caching.remote.DummyCache"
31 | system-check-enabled = true
--------------------------------------------------------------------------------
/code/authorizer/src/main/resources/server_error.soy:
--------------------------------------------------------------------------------
1 | /**
2 | Copyright 2020 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | {namespace Authorizer.Templates}
18 |
19 | {template .server_error}
20 |
21 |
22 | GCP Token Broker
23 |
24 |
25 |
Server error
26 |
27 |
28 | {/template}
29 |
--------------------------------------------------------------------------------
/code/authorizer/src/main/resources/success.soy:
--------------------------------------------------------------------------------
1 | /**
2 | Copyright 2020 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | {namespace Authorizer.Templates}
18 |
19 | {template .success}
20 |
21 |
22 | Authorization complete
23 |
24 |
25 |
Authorization complete
26 |
Congratulations! You are now authorized to use the GCP Token Broker.
27 |
28 |
29 | {/template}
--------------------------------------------------------------------------------
/code/authorizer/src/test/java/com/google/cloud/broker/apps/authorizer/TemplateTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.apps.authorizer;
18 |
19 | import com.google.common.collect.ImmutableMap;
20 | import com.google.common.io.Resources;
21 | import com.google.template.soy.SoyFileSet;
22 | import com.google.template.soy.jbcsrc.api.SoySauce;
23 | import java.util.Map;
24 | import org.junit.BeforeClass;
25 | import org.junit.Test;
26 |
27 | public class TemplateTest {
28 | private static SoySauce soySauce;
29 |
30 | @BeforeClass
31 | public static void setup() {
32 | SoyFileSet sfs =
33 | SoyFileSet.builder()
34 | .add(Resources.getResource("index.soy"))
35 | .add(Resources.getResource("success.soy"))
36 | .build();
37 | soySauce = sfs.compileTemplates();
38 | }
39 |
40 | @Test
41 | public void testIndex() {
42 | Map data =
43 | ImmutableMap.builder()
44 | .put("principal", "user@EXAMPLE.COM")
45 | .put("email", "user@example.com")
46 | .put("picture", "https://cdn.example.com/user.jpg")
47 | .build();
48 | String content =
49 | soySauce
50 | .renderTemplate("Authorizer.Templates.success")
51 | .setData(data)
52 | .renderHtml()
53 | .get()
54 | .getContent();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/code/broker-server/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | FROM ubuntu:18.04
13 |
14 | COPY ./code/broker-server/install.sh /base/code/broker-server/install.sh
15 |
16 | RUN /base/code/broker-server/install.sh
17 |
18 | COPY ./code/broker-server/target/broker-server-*-jar-with-dependencies.jar /classpath/broker-server.jar
19 | COPY ./code/extensions/caching/cloud-datastore/target/cache-backend-cloud-datastore-*-jar-with-dependencies.jar /classpath/cache-backend-cloud-datastore.jar
20 | COPY ./code/extensions/caching/redis/target/cache-backend-redis-*-jar-with-dependencies.jar /classpath/cache-backend-redis.jar
21 | COPY ./code/extensions/database/jdbc/target/database-backend-jdbc-*-jar-with-dependencies.jar /classpath/database-backend-jdbc.jar
22 | COPY ./code/extensions/database/cloud-datastore/target/database-backend-cloud-datastore-*-jar-with-dependencies.jar /classpath/database-backend-cloud-datastore.jar
23 | COPY ./code/extensions/encryption/cloud-kms/target/encryption-backend-cloud-kms-*-jar-with-dependencies.jar /classpath/encryption-backend-cloud-kms.jar
24 |
25 | WORKDIR /base/code/broker
26 |
27 | ENTRYPOINT ["java", "-cp", "/classpath/*", "com.google.cloud.broker.apps.brokerserver.BrokerServer"]
--------------------------------------------------------------------------------
/code/broker-server/descriptor.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
27 | jar-with-dependencies
28 |
29 | jar
30 |
31 | false
32 |
33 |
34 | /
35 | true
36 | true
37 | runtime
38 |
39 |
40 |
41 |
42 | metaInf-services
43 |
44 |
45 |
--------------------------------------------------------------------------------
/code/broker-server/install-dev.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Google LLC
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | set -xeuo pipefail
15 |
16 | source "/base/code/broker-server/install.sh"
17 |
18 | # Maven and its dependencies
19 | apt-get install -y libatomic1 maven
20 |
21 | # Create a script to restart services
22 | touch /restart-services.sh
23 | chmod u+x /restart-services.sh
24 |
25 | # PostgreSQL
26 | echo exit 0 > /usr/sbin/policy-rc.d
27 | DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql
28 | echo "CREATE ROLE testuser LOGIN ENCRYPTED PASSWORD 'UNSECURE-PASSWORD';" | su postgres -c "psql"
29 | su postgres -c "createdb broker --owner testuser"
30 | echo "service postgresql restart" >> /restart-services.sh
31 | # Make the Postgres server available outside the container
32 | sed -Ei "s/#listen_addresses\s+=\s+'localhost'/listen_addresses = '*'/g" /etc/postgresql/*/main/postgresql.conf
33 | echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/14/main/pg_hba.conf
34 |
35 | # MariaDB
36 | apt install -y mariadb-server
37 | echo "CREATE DATABASE broker DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" | mariadb
38 | echo "CREATE USER 'testuser' IDENTIFIED BY 'UNSECURE-PASSWORD';" | mariadb
39 | echo "GRANT ALL privileges ON *.* TO 'testuser'@'%';" | mariadb
40 | echo "service mariadb restart" >> /restart-services.sh
41 | # Make the MariaDB server available outside the container
42 | sed -Ei 's/bind-address\s+=\s+127.0.0.1/bind-address=0.0.0.0/g' /etc/mysql/mariadb.conf.d/50-server.cnf
43 |
44 | # Redis
45 | apt-get install -y redis-server
46 | # Apparently need to run 'shutdown' as 'service stop' and 'service restart' don't seem to kill the process
47 | echo "redis-cli shutdown; service redis-server start" >> /restart-services.sh
48 | # Make the Redis server available outside the container
49 | sed 's/^bind 127.0.0.1 ::1/bind 0.0.0.0/' -i /etc/redis/redis.conf
50 | sed 's/^protected-mode yes/protected-mode no/' -i /etc/redis/redis.conf
51 |
52 | # Node.JS tools
53 | apt install -y npm
54 | npm install --global remark-cli remark-validate-links # Used for code linting (`./run.sh lint`)
55 | export NODE_PATH="/usr/local/lib/node_modules"
56 |
57 | # (Re)start all services
58 | /restart-services.sh
--------------------------------------------------------------------------------
/code/broker-server/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Google LLC
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | apt-get update
15 |
16 | DEBIAN_FRONTEND=noninteractive apt-get install -y \
17 | krb5-user \
18 | libkrb5-dev \
19 | openjdk-11-jre-headless
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/ClientAddressServerInterceptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver;
13 |
14 | import io.grpc.*;
15 |
16 | public class ClientAddressServerInterceptor implements ServerInterceptor {
17 |
18 | public static final Context.Key CLIENT_ADDRESS_CONTEXT_KEY = Context.key("ClientAddress");
19 |
20 | @Override
21 | public ServerCall.Listener interceptCall(
22 | ServerCall serverCall,
23 | Metadata metadata,
24 | ServerCallHandler serverCallHandler) {
25 | String clientAddress =
26 | serverCall.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR).toString();
27 | Context ctx = Context.current().withValue(CLIENT_ADDRESS_CONTEXT_KEY, clientAddress);
28 | return Contexts.interceptCall(ctx, serverCall, metadata, serverCallHandler);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/AccessToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens;
13 |
14 | import com.fasterxml.jackson.annotation.JsonCreator;
15 | import com.fasterxml.jackson.annotation.JsonProperty;
16 |
17 | public class AccessToken {
18 |
19 | private String value;
20 | private long expiresAt;
21 |
22 | @JsonCreator
23 | public AccessToken(
24 | @JsonProperty("value") String value, @JsonProperty("expiresAt") long expiresAt) {
25 | this.value = value;
26 | this.expiresAt = expiresAt;
27 | }
28 |
29 | @JsonProperty("value")
30 | public String getValue() {
31 | return value;
32 | }
33 |
34 | @JsonProperty("expiresAt")
35 | public long getExpiresAt() {
36 | return expiresAt;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/AbstractProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.accesstokens.AccessToken;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.utils.InstanceUtils;
17 | import java.util.List;
18 |
19 | public abstract class AbstractProvider {
20 |
21 | private static AbstractProvider instance;
22 |
23 | public static AbstractProvider getInstance() {
24 | String className = AppSettings.getInstance().getString(AppSettings.PROVIDER_BACKEND);
25 | if (instance == null || !className.equals(instance.getClass().getCanonicalName())) {
26 | instance = (AbstractProvider) InstanceUtils.invokeConstructor(className);
27 | }
28 | return instance;
29 | }
30 |
31 | public abstract AccessToken getAccessToken(String googleIdentity, List scopes);
32 | }
33 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/AbstractUserProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | public abstract class AbstractUserProvider extends AbstractProvider {}
15 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/HybridProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.accesstokens.AccessToken;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.utils.InstanceUtils;
17 | import java.util.List;
18 |
19 | public class HybridProvider extends AbstractProvider {
20 |
21 | AbstractUserProvider userProvider;
22 | ServiceAccountProvider serviceAccountProvider;
23 |
24 | public HybridProvider() {
25 | String className = AppSettings.getInstance().getString(AppSettings.HYBRID_USER_PROVIDER);
26 | userProvider = (AbstractUserProvider) InstanceUtils.invokeConstructor(className);
27 | serviceAccountProvider = new ServiceAccountProvider();
28 | }
29 |
30 | @Override
31 | public AccessToken getAccessToken(String googleIdentity, List scopes) {
32 | if (googleIdentity.endsWith(".iam.gserviceaccount.com")) {
33 | return serviceAccountProvider.getAccessToken(googleIdentity, scopes);
34 | } else {
35 | return userProvider.getAccessToken(googleIdentity, scopes);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/RevokeRefreshTokens.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import com.google.cloud.broker.database.backends.AbstractDatabaseBackend;
15 | import com.google.cloud.broker.database.models.Model;
16 | import com.google.cloud.broker.oauth.RefreshToken;
17 | import com.google.cloud.broker.oauth.RefreshTokenUtils;
18 | import com.google.cloud.broker.utils.TimeUtils;
19 | import java.lang.invoke.MethodHandles;
20 | import java.util.List;
21 | import org.slf4j.Logger;
22 | import org.slf4j.LoggerFactory;
23 |
24 | public class RevokeRefreshTokens {
25 |
26 | private static final Class> klass = MethodHandles.lookup().lookupClass();
27 | private static final Logger logger = LoggerFactory.getLogger(klass);
28 |
29 | public static void main(String[] args) {
30 | long numHours;
31 | if (args.length == 1) {
32 | numHours = Long.parseLong(args[0]);
33 | } else {
34 | throw new IllegalArgumentException("Wrong arguments");
35 | }
36 | long numMilliseconds = numHours * 3600 * 1000;
37 | long now = TimeUtils.currentTimeMillis();
38 | List models = AbstractDatabaseBackend.getInstance().getAll(RefreshToken.class);
39 | int numRevokedToken = 0;
40 | for (Model model : models) {
41 | RefreshToken token = (RefreshToken) model;
42 | if (now >= token.getCreationTime() + numMilliseconds) {
43 | // Revoke the token
44 | RefreshTokenUtils.revoke(token);
45 | // Delete the token from the database
46 | AbstractDatabaseBackend.getInstance().delete(token);
47 | numRevokedToken++;
48 | }
49 | }
50 | logger.info(
51 | klass.getSimpleName() + " - Revoked and deleted refresh token(s): " + numRevokedToken);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/ServiceAccountProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import com.google.auth.oauth2.GoogleCredentials;
15 | import com.google.auth.oauth2.ImpersonatedCredentials;
16 | import com.google.cloud.broker.apps.brokerserver.accesstokens.AccessToken;
17 | import io.grpc.Status;
18 | import java.io.IOException;
19 | import java.util.List;
20 |
21 | public class ServiceAccountProvider extends AbstractProvider {
22 |
23 | @Override
24 | public AccessToken getAccessToken(String googleIdentity, List scopes) {
25 | if (!googleIdentity.endsWith(".iam.gserviceaccount.com")) {
26 | throw new IllegalArgumentException(
27 | "Google identity `" + googleIdentity + "` is not a service account");
28 | }
29 | try {
30 | GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
31 | ImpersonatedCredentials impersonatedCredentials =
32 | ImpersonatedCredentials.create(credentials, googleIdentity, null, scopes, 3600);
33 | com.google.auth.oauth2.AccessToken token = impersonatedCredentials.refreshAccessToken();
34 | return new AccessToken(token.getTokenValue(), token.getExpirationTime().getTime());
35 | } catch (IOException e) {
36 | throw Status.PERMISSION_DENIED.asRuntimeException();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/experimental/JSONFileCredentialsProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers.experimental;
13 |
14 | import com.google.auth.oauth2.GoogleCredentials;
15 | import com.google.cloud.broker.apps.brokerserver.accesstokens.AccessToken;
16 | import com.google.cloud.broker.apps.brokerserver.accesstokens.providers.AbstractProvider;
17 | import com.google.cloud.broker.settings.AppSettings;
18 | import io.grpc.Status;
19 | import java.io.ByteArrayInputStream;
20 | import java.io.IOException;
21 | import java.nio.file.Files;
22 | import java.nio.file.NoSuchFileException;
23 | import java.nio.file.Path;
24 | import java.nio.file.Paths;
25 | import java.util.List;
26 |
27 | /**
28 | * Uses the credentials in a JSON file to generate access tokens. The JSON file can contain a
29 | * Service Account key file in JSON format from the Google Developers Console or a stored user
30 | * credential using the format supported by the Cloud SDK. This is an experimental backend that
31 | * might be removed or modified in a future release. This is NOT recommended for production.
32 | */
33 | public class JSONFileCredentialsProvider extends AbstractProvider {
34 |
35 | private static String AUTHZ_ERROR_MESSAGE =
36 | "GCP Token Broker authorization is invalid or has expired for identity: %s";
37 |
38 | @Override
39 | public AccessToken getAccessToken(String googleIdentity, List scopes) {
40 | try {
41 | String basedir =
42 | AppSettings.getInstance().getString(AppSettings.JSON_FILE_CREDENTIALS_PROVIDER_BASE_DIR);
43 | Path path = Paths.get(basedir, googleIdentity.split("@")[0] + ".json");
44 | GoogleCredentials credentials =
45 | GoogleCredentials.fromStream(new ByteArrayInputStream(Files.readAllBytes(path)));
46 | com.google.auth.oauth2.AccessToken token =
47 | credentials.createScoped(scopes).refreshAccessToken();
48 | return new AccessToken(token.getTokenValue(), token.getExpirationTime().getTime());
49 | } catch (NoSuchFileException e) {
50 | throw Status.PERMISSION_DENIED
51 | .withDescription(String.format(AUTHZ_ERROR_MESSAGE, googleIdentity))
52 | .asRuntimeException();
53 | } catch (IOException e) {
54 | throw new RuntimeException(e);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/sessions/SessionAuthenticator.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.sessions;
13 |
14 | import com.google.cloud.broker.authentication.AuthorizationHeaderServerInterceptor;
15 | import io.grpc.Status;
16 |
17 | public class SessionAuthenticator {
18 |
19 | public Session authenticateSession() {
20 | String authorizationHeader =
21 | AuthorizationHeaderServerInterceptor.BROKER_AUTHORIZATION_CONTEXT_KEY.get();
22 |
23 | // Make sure this is indeed
24 | if (!authorizationHeader.startsWith("BrokerSession ")) {
25 | return null;
26 | }
27 |
28 | // Extract the session token from the authorization header
29 | String token = authorizationHeader.split("\\s")[1];
30 |
31 | Session session = (Session) new SessionCacheFetcher(token).fetch();
32 |
33 | if (session.isExpired()) {
34 | throw Status.UNAUTHENTICATED
35 | .withDescription("Expired session ID: " + session.getId())
36 | .asRuntimeException();
37 | }
38 |
39 | return session;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/sessions/SessionCacheFetcher.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.sessions;
13 |
14 | import com.fasterxml.jackson.databind.ObjectMapper;
15 | import com.google.cloud.broker.caching.CacheFetcher;
16 | import com.google.cloud.broker.settings.AppSettings;
17 | import java.io.IOException;
18 |
19 | public class SessionCacheFetcher extends CacheFetcher {
20 |
21 | private String rawToken;
22 |
23 | public SessionCacheFetcher(String rawToken) {
24 | this.rawToken = rawToken;
25 | // Disallow remote cache because the cache key contains sensitive information
26 | // (i.e. the session tokens)
27 | this.allowRemoteCache = false;
28 | }
29 |
30 | @Override
31 | protected String getCacheKey() {
32 | return String.format("session-%s", rawToken);
33 | }
34 |
35 | @Override
36 | protected int getLocalCacheTime() {
37 | return AppSettings.getInstance().getInt(AppSettings.SESSION_LOCAL_CACHE_TIME);
38 | }
39 |
40 | @Override
41 | protected int getRemoteCacheTime() {
42 | // Remote cache not enabled
43 | throw new UnsupportedOperationException();
44 | }
45 |
46 | @Override
47 | protected Object computeResult() {
48 | return SessionTokenUtils.getSessionFromRawToken(rawToken);
49 | }
50 |
51 | @Override
52 | protected Object fromJson(String json) throws IOException {
53 | ObjectMapper objectMapper = new ObjectMapper();
54 | return objectMapper.readValue(json, Session.class);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/sessions/SessionCleanup.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.sessions;
13 |
14 | import com.google.cloud.broker.database.backends.AbstractDatabaseBackend;
15 | import com.google.cloud.broker.utils.TimeUtils;
16 | import java.lang.invoke.MethodHandles;
17 | import org.slf4j.Logger;
18 | import org.slf4j.LoggerFactory;
19 |
20 | public class SessionCleanup {
21 |
22 | private static final Class> klass = MethodHandles.lookup().lookupClass();
23 | private static final Logger logger = LoggerFactory.getLogger(klass);
24 |
25 | public static void main(String[] args) {
26 | Integer numItems = null;
27 | if (args.length > 0) {
28 | numItems = Integer.parseInt(args[0]);
29 | }
30 | long now = TimeUtils.currentTimeMillis();
31 | int numDeletedSessions =
32 | AbstractDatabaseBackend.getInstance()
33 | .deleteExpiredItems(Session.class, "expiresAt", now, numItems);
34 | logger.info(klass.getSimpleName() + " - Deleted expired session(s): " + numDeletedSessions);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/sessions/SessionToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.sessions;
13 |
14 | class SessionToken {
15 |
16 | private String sessionId;
17 | private byte[] signature;
18 |
19 | SessionToken(String sessionId, byte[] signature) {
20 | this.sessionId = sessionId;
21 | this.signature = signature;
22 | }
23 |
24 | String getSessionId() {
25 | return sessionId;
26 | }
27 |
28 | byte[] getSignature() {
29 | return signature;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/validation/GrpcRequestValidation.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.validation;
13 |
14 | import io.grpc.Status;
15 | import java.util.*;
16 |
17 | public class GrpcRequestValidation {
18 |
19 | public static void validateParameterIsEmpty(String parameter, String value) {
20 | if (value.length() > 0) {
21 | throw Status.INVALID_ARGUMENT
22 | .withDescription(String.format("Request's parameter `%s` must be empty", parameter))
23 | .asRuntimeException();
24 | }
25 | }
26 |
27 | public static void validateParameterIsEmpty(String parameter, List values) {
28 | if (values.size() > 0) {
29 | throw Status.INVALID_ARGUMENT
30 | .withDescription(String.format("Request's parameter `%s` must be empty", parameter))
31 | .asRuntimeException();
32 | }
33 | }
34 |
35 | public static void validateParameterNotEmpty(String parameter, String value) {
36 | if (value.length() == 0) {
37 | throw Status.INVALID_ARGUMENT
38 | .withDescription(String.format("Request must provide `%s`", parameter))
39 | .asRuntimeException();
40 | }
41 | }
42 |
43 | public static void validateParameterNotEmpty(String parameter, List values) {
44 | if (values.size() == 0) {
45 | throw Status.INVALID_ARGUMENT
46 | .withDescription(String.format("Request must provide `%s`", parameter))
47 | .asRuntimeException();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/java/com/google/cloud/broker/apps/brokerserver/validation/ScopeValidation.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.validation;
13 |
14 | import com.google.cloud.broker.settings.AppSettings;
15 | import io.grpc.Status;
16 | import java.util.HashSet;
17 | import java.util.List;
18 | import java.util.Set;
19 |
20 | public class ScopeValidation {
21 |
22 | public static void validateScopes(List scopes) {
23 | List allowlist = AppSettings.getInstance().getStringList(AppSettings.SCOPES_ALLOWLIST);
24 | Set scopeSet = new HashSet(scopes);
25 | Set allowlistSet = new HashSet(allowlist);
26 | if (!allowlistSet.containsAll(scopeSet)) {
27 | throw Status.PERMISSION_DENIED
28 | .withDescription(
29 | String.format("`[%s]` are not allowlisted scopes", String.join(",", scopes)))
30 | .asRuntimeException();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/proto/broker.proto:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | syntax = "proto3";
13 |
14 | option java_multiple_files = true;
15 | option java_package = "com.google.cloud.broker.apps.brokerserver.protobuf";
16 | option java_outer_classname = "BrokerProto";
17 |
18 | package com.google.cloud.broker.apps.brokerserver.protobuf;
19 |
20 |
21 | // Get session token request/response --------------------------
22 |
23 | message GetSessionTokenRequest {
24 | repeated string scopes = 1;
25 | string owner = 2;
26 | string target = 3;
27 | string renewer = 4;
28 | }
29 |
30 | message GetSessionTokenResponse {
31 | string session_token = 1;
32 | }
33 |
34 | // Renew session token request/response ------------------------
35 |
36 | message RenewSessionTokenRequest {
37 | string session_token = 1;
38 | }
39 |
40 | message RenewSessionTokenResponse {
41 | int64 expires_at = 2;
42 | }
43 |
44 | // Cancel session token request/response -----------------------
45 |
46 | message CancelSessionTokenRequest {
47 | string session_token = 1;
48 | }
49 |
50 | message CancelSessionTokenResponse {
51 | }
52 |
53 | // Get access token request/response ---------------------------
54 |
55 | message GetAccessTokenRequest {
56 | repeated string scopes = 1;
57 | string owner = 2;
58 | string target = 3;
59 | }
60 |
61 | message GetAccessTokenResponse {
62 | string access_token = 1;
63 | int64 expires_at = 2;
64 | }
65 |
66 |
67 | // Broker service -----------------------------------------
68 |
69 | service Broker {
70 | rpc GetSessionToken(GetSessionTokenRequest) returns (GetSessionTokenResponse) {}
71 | rpc RenewSessionToken(RenewSessionTokenRequest) returns (RenewSessionTokenResponse) {}
72 | rpc CancelSessionToken(CancelSessionTokenRequest) returns (CancelSessionTokenResponse) {}
73 | rpc GetAccessToken(GetAccessTokenRequest) returns (GetAccessTokenResponse) {}
74 | }
--------------------------------------------------------------------------------
/code/broker-server/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/code/broker-server/src/main/resources/reference.conf:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | # Default values for some of the broker server settings
13 |
14 | server {
15 | host = "0.0.0.0"
16 | port = 8080
17 | tls {
18 | enabled = true
19 | }
20 | }
21 |
22 | sessions {
23 | local-cache-time = 30
24 | maximum-lifetime = 604800000
25 | renew-period = 86400000
26 | }
27 |
28 | proxy-users = []
29 |
30 | scopes {
31 | allowlist = ["https://www.googleapis.com/auth/devstorage.read_write"]
32 | }
33 |
34 | provider {
35 | backend = "com.google.cloud.broker.apps.brokerserver.accesstokens.providers.HybridProvider"
36 | access-tokens {
37 | local-cache-time = 30
38 | remote-cache-time = 60
39 | boundary-permissions = [
40 | "inRole:roles/storage.objectAdmin",
41 | "inRole:roles/storage.legacyBucketReader"
42 | ]
43 | }
44 |
45 | # Specific providers' settings
46 | hybrid {
47 | user-provider = "com.google.cloud.broker.apps.brokerserver.accesstokens.providers.RefreshTokenProvider"
48 | }
49 | json-file-credentials {
50 | base-dir = ""
51 | }
52 | }
53 |
54 | user-mapping {
55 | mapper = "com.google.cloud.broker.usermapping.KerberosUserMapper"
56 | }
57 |
58 | remote-cache {
59 | backend = "com.google.cloud.broker.caching.remote.RedisCache"
60 |
61 | # Specific backends' settings
62 | redis {
63 | host = "localhost"
64 | port = 6379
65 | db = 0
66 | }
67 | }
68 |
69 | authentication {
70 | backend = "com.google.cloud.broker.authentication.backends.SpnegoAuthenticator"
71 | }
72 |
73 | logging {
74 | level = "INFO"
75 | }
76 |
77 | database {
78 | backend = "com.google.cloud.broker.database.backends.CloudDatastoreBackend"
79 | }
80 |
81 | encryption {
82 | backend = "com.google.cloud.broker.encryption.backends.CloudKMSBackend"
83 | }
84 |
85 | secret-manager {
86 | downloads = []
87 | }
88 |
89 | system-check-enabled = true
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/accesstokens/MockAccessBoundary.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens;
13 |
14 | import static org.mockito.ArgumentMatchers.any;
15 | import static org.mockito.ArgumentMatchers.anyString;
16 | import static org.powermock.api.mockito.PowerMockito.mockStatic;
17 |
18 | import org.powermock.api.mockito.PowerMockito;
19 |
20 | public class MockAccessBoundary {
21 |
22 | public static void mock() {
23 | mockStatic(AccessBoundaryUtils.class);
24 | PowerMockito.when(AccessBoundaryUtils.addAccessBoundary(any(), anyString()))
25 | .thenAnswer(
26 | invocation -> {
27 | AccessToken accessToken = (AccessToken) invocation.getArgument(0);
28 | String target = (String) invocation.getArgument(1);
29 | return new AccessToken(
30 | accessToken.getValue() + ";Target=" + target, accessToken.getExpiresAt());
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/AbstractProviderTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.settings.AppSettings;
17 | import com.google.cloud.broker.settings.SettingsOverride;
18 | import java.util.Map;
19 | import org.junit.Test;
20 |
21 | public class AbstractProviderTest {
22 |
23 | @Test
24 | public void testGetInstance() {
25 | try (SettingsOverride override =
26 | SettingsOverride.apply(Map.of(AppSettings.PROVIDER_BACKEND, "com.example.DoesNotExist"))) {
27 | try {
28 | AbstractProvider.getInstance();
29 | fail();
30 | } catch (RuntimeException e) {
31 | assertEquals("java.lang.ClassNotFoundException: com.example.DoesNotExist", e.getMessage());
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/DomainWideDelegationAuthorityProviderTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import io.grpc.Status;
17 | import io.grpc.StatusRuntimeException;
18 | import java.util.List;
19 | import org.junit.Test;
20 |
21 | public class DomainWideDelegationAuthorityProviderTest {
22 |
23 | // TODO: Still needs tests:
24 | // - Happy path
25 |
26 | private static final List SCOPES =
27 | List.of("https://www.googleapis.com/auth/devstorage.read_write");
28 |
29 | @Test
30 | public void testUnauthorized() {
31 | DomainWideDelegationAuthorityProvider provider = new DomainWideDelegationAuthorityProvider();
32 | try {
33 | provider.getAccessToken("bob@example.com", SCOPES);
34 | fail();
35 | } catch (StatusRuntimeException e) {
36 | assertEquals(Status.PERMISSION_DENIED.getCode(), e.getStatus().getCode());
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/HybridProviderTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import static org.junit.Assert.*;
15 | import static org.junit.Assert.assertTrue;
16 |
17 | import com.google.cloud.broker.apps.brokerserver.accesstokens.AccessToken;
18 | import com.google.cloud.broker.database.backends.DummyDatabaseBackend;
19 | import com.google.cloud.broker.settings.AppSettings;
20 | import com.google.cloud.broker.settings.SettingsOverride;
21 | import java.nio.charset.StandardCharsets;
22 | import java.util.List;
23 | import java.util.Map;
24 | import org.junit.*;
25 |
26 | public class HybridProviderTest {
27 |
28 | // TODO: Still needs tests:
29 | // - Happy path.
30 |
31 | private static final List SCOPES =
32 | List.of("https://www.googleapis.com/auth/devstorage.read_write");
33 | private static final String projectId =
34 | AppSettings.getInstance().getString(AppSettings.GCP_PROJECT);
35 |
36 | @ClassRule
37 | public static SettingsOverride settingsOverride =
38 | new SettingsOverride(
39 | Map.of(
40 | AppSettings.USER_MAPPER, "com.google.cloud.broker.usermapping.MockUserMapper",
41 | AppSettings.HYBRID_USER_PROVIDER,
42 | "com.google.cloud.broker.apps.brokerserver.accesstokens.providers.MockProvider"));
43 |
44 | @After
45 | public void teardown() {
46 | // Clear the database
47 | DummyDatabaseBackend.getCache().clear();
48 | }
49 |
50 | @Test
51 | public void testUser() {
52 | HybridProvider provider = new HybridProvider();
53 | AccessToken accessToken = provider.getAccessToken("alice@example.com", SCOPES);
54 | assertEquals(
55 | "FakeAccessToken/GoogleIdentity=alice@example.com;Scopes=" + String.join(",", SCOPES),
56 | accessToken.getValue());
57 | }
58 |
59 | @Test
60 | public void testServiceAccount() {
61 | HybridProvider provider = new HybridProvider();
62 | AccessToken accessToken =
63 | provider.getAccessToken("alice-shadow@" + projectId + ".iam.gserviceaccount.com", SCOPES);
64 | assertTrue(accessToken.getValue().startsWith("ya29."));
65 | assertEquals(1024, accessToken.getValue().getBytes(StandardCharsets.UTF_8).length);
66 | assertTrue(accessToken.getExpiresAt() > 0);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/MockProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.accesstokens.AccessToken;
15 | import java.util.List;
16 |
17 | /** Mock provider only used for testing. Do NOT use in production! */
18 | public class MockProvider extends AbstractUserProvider {
19 |
20 | @Override
21 | public AccessToken getAccessToken(String googleIdentity, List scopes) {
22 | return new AccessToken(
23 | "FakeAccessToken/GoogleIdentity=" + googleIdentity + ";Scopes=" + String.join(",", scopes),
24 | 999999999L);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/accesstokens/providers/RefreshTokenProviderTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.accesstokens.providers;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.database.backends.DummyDatabaseBackend;
17 | import com.google.cloud.broker.settings.AppSettings;
18 | import com.google.cloud.broker.settings.SettingsOverride;
19 | import io.grpc.Status;
20 | import io.grpc.StatusRuntimeException;
21 | import java.util.List;
22 | import java.util.Map;
23 | import org.junit.*;
24 |
25 | public class RefreshTokenProviderTest {
26 |
27 | // TODO: Still needs tests:
28 | // - Happy path.
29 |
30 | private static final List SCOPES =
31 | List.of("https://www.googleapis.com/auth/devstorage.read_write");
32 |
33 | @ClassRule
34 | public static SettingsOverride settingsOverride =
35 | new SettingsOverride(
36 | Map.of(
37 | AppSettings.DATABASE_BACKEND,
38 | "com.google.cloud.broker.database.backends.DummyDatabaseBackend",
39 | AppSettings.USER_MAPPER, "com.google.cloud.broker.usermapping.MockUserMapper"));
40 |
41 | @After
42 | public void teardown() {
43 | // Clear the database
44 | DummyDatabaseBackend.getCache().clear();
45 | }
46 |
47 | @Test
48 | public void testUnauthorized() {
49 | RefreshTokenProvider provider = new RefreshTokenProvider();
50 | try {
51 | provider.getAccessToken("bob@example.com", SCOPES);
52 | fail("StatusRuntimeException not thrown");
53 | } catch (StatusRuntimeException e) {
54 | assertEquals(Status.PERMISSION_DENIED.getCode(), e.getStatus().getCode());
55 | assertEquals(
56 | "GCP Token Broker authorization is invalid or has expired for identity: bob@example.com",
57 | e.getStatus().getDescription());
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/apps/brokerserver/sessions/SessionTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.apps.brokerserver.sessions;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.database.models.Model;
17 | import java.util.HashMap;
18 | import org.junit.Test;
19 |
20 | public class SessionTest {
21 |
22 | private static final String ALICE = "alice@EXAMPLE.COM";
23 | private static final String YARN = "yarn@FOO.BAR";
24 | private static final String GCS = "https://www.googleapis.com/auth/devstorage.read_write";
25 | private static final String MOCK_BUCKET = "//storage.googleapis.com/projects/_/buckets/example";
26 |
27 | // TODO: testToMap
28 |
29 | @Test
30 | public void testFromMap() {
31 | HashMap values = new HashMap();
32 | values.put("id", "123456789");
33 | values.put("owner", ALICE);
34 | values.put("renewer", YARN);
35 | values.put("target", MOCK_BUCKET);
36 | values.put("scopes", GCS);
37 | values.put("creationTime", 11111111111111L);
38 | values.put("expiresAt", 2222222222222L);
39 |
40 | Session session = (Session) Model.fromMap(Session.class, values);
41 | assertEquals("123456789", session.getId());
42 | assertEquals(ALICE, session.getOwner());
43 | assertEquals(YARN, session.getRenewer());
44 | assertEquals(MOCK_BUCKET, session.getTarget());
45 | assertEquals(GCS, session.getScopes());
46 | assertEquals(11111111111111L, session.getCreationTime().longValue());
47 | assertEquals(2222222222222L, session.getExpiresAt().longValue());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/authentication/backends/MockAuthenticator.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.authentication.backends;
13 |
14 | import io.grpc.Status;
15 |
16 | /**
17 | * Used only for testing. Do NOT use in production. This is a dummy authenticator that returns the
18 | * provided token as the authenticated user. In other terms, to allow this authenticator to
19 | * authenticate a user, simply pass the user name in the token, e.g.: "Negotiate: alice@EXAMPLE.COM"
20 | */
21 | public class MockAuthenticator extends AbstractAuthenticationBackend {
22 |
23 | public MockAuthenticator() {}
24 |
25 | @Override
26 | public String authenticateUser(String authorizationHeader) {
27 | if (!authorizationHeader.startsWith("Negotiate ")) {
28 | throw Status.UNAUTHENTICATED.asRuntimeException();
29 | }
30 | return authorizationHeader.split("\\s")[1];
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/code/broker-server/src/test/java/com/google/cloud/broker/usermapping/MockUserMapper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.usermapping;
13 |
14 | public class MockUserMapper extends AbstractUserMapper {
15 |
16 | @Override
17 | public String map(String name) throws IllegalArgumentException {
18 | return name.split("@")[0] + "@altostrat.com";
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/connect/BrokerServerInfo.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.connect;
13 |
14 | public class BrokerServerInfo {
15 |
16 | private String serverUri;
17 | private String kerberosPrincipal;
18 | private String certificate;
19 | private String certificatePath;
20 |
21 | public BrokerServerInfo(
22 | String serverUri, String kerberosPrincipal, String certificate, String certificatePath) {
23 | this.serverUri = serverUri;
24 | this.kerberosPrincipal = kerberosPrincipal;
25 | this.certificate = certificate;
26 | this.certificatePath = certificatePath;
27 | }
28 |
29 | public String getServerUri() {
30 | return serverUri;
31 | }
32 |
33 | public void setServerUri(String serverUri) {
34 | this.serverUri = serverUri;
35 | }
36 |
37 | public String getKerberosPrincipal() {
38 | return kerberosPrincipal;
39 | }
40 |
41 | public void setKerberosPrincipal(String kerberosPrincipal) {
42 | this.kerberosPrincipal = kerberosPrincipal;
43 | }
44 |
45 | public String getCertificate() {
46 | return certificate;
47 | }
48 |
49 | public void setCertificate(String certificate) {
50 | this.certificate = certificate;
51 | }
52 |
53 | public String getCertificatePath() {
54 | return certificatePath;
55 | }
56 |
57 | public void setCertificatePath(String certificatePath) {
58 | this.certificatePath = certificatePath;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/credentials/BrokerKerberosCredentials.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.credentials;
13 |
14 | import com.google.auth.oauth2.AccessToken;
15 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
16 | import com.google.cloud.broker.client.endpoints.GetAccessToken;
17 |
18 | public class BrokerKerberosCredentials extends BrokerBaseCredentials {
19 |
20 | private String owner;
21 | private Iterable scopes;
22 | private String target;
23 |
24 | public BrokerKerberosCredentials(
25 | BrokerServerInfo serverInfo, String owner, Iterable scopes, String target) {
26 | super(serverInfo);
27 | this.owner = owner;
28 | this.scopes = scopes;
29 | this.target = target;
30 | }
31 |
32 | @Override
33 | public AccessToken refreshAccessToken() {
34 | return GetAccessToken.submitDirectAuth(serverInfo, owner, scopes, target);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/credentials/BrokerSessionCredentials.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.credentials;
13 |
14 | import com.google.auth.oauth2.AccessToken;
15 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
16 | import com.google.cloud.broker.client.endpoints.GetAccessToken;
17 |
18 | public class BrokerSessionCredentials extends BrokerBaseCredentials {
19 |
20 | private String sessionToken;
21 |
22 | public BrokerSessionCredentials(BrokerServerInfo serverInfo, String sessionToken) {
23 | super(serverInfo);
24 | this.sessionToken = sessionToken;
25 | }
26 |
27 | public AccessToken refreshAccessToken() {
28 | return GetAccessToken.submitDelegatedAuth(serverInfo, sessionToken);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/endpoints/CancelSessionToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.endpoints;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.protobuf.CancelSessionTokenRequest;
15 | import com.google.cloud.broker.client.connect.BrokerGateway;
16 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
17 |
18 | public class CancelSessionToken {
19 |
20 | public static void submit(BrokerServerInfo serverInfo, String sessionToken) {
21 | BrokerGateway gateway = new BrokerGateway(serverInfo);
22 | gateway.setSPNEGOToken();
23 | CancelSessionTokenRequest request =
24 | CancelSessionTokenRequest.newBuilder().setSessionToken(sessionToken).build();
25 | gateway.getStub().cancelSessionToken(request);
26 | gateway.getManagedChannel().shutdown();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/endpoints/GetAccessToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.endpoints;
13 |
14 | import com.google.auth.oauth2.AccessToken;
15 | import com.google.cloud.broker.apps.brokerserver.protobuf.GetAccessTokenRequest;
16 | import com.google.cloud.broker.apps.brokerserver.protobuf.GetAccessTokenResponse;
17 | import com.google.cloud.broker.client.connect.BrokerGateway;
18 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
19 | import java.util.Date;
20 |
21 | public class GetAccessToken {
22 |
23 | public static AccessToken submitDirectAuth(
24 | BrokerServerInfo serverInfo, String owner, Iterable scopes, String target) {
25 | BrokerGateway gateway = new BrokerGateway(serverInfo);
26 | try {
27 | gateway.setSPNEGOToken();
28 | } catch (Exception e) {
29 | throw new RuntimeException(
30 | String.format(
31 | "Error while getting SPNEGO token for owner=`%s`, scopes=`%s`, target=`%s`",
32 | owner, scopes, target),
33 | e);
34 | }
35 | GetAccessTokenRequest request =
36 | GetAccessTokenRequest.newBuilder()
37 | .addAllScopes(scopes)
38 | .setOwner(owner)
39 | .setTarget(target)
40 | .build();
41 | GetAccessTokenResponse response = gateway.getStub().getAccessToken(request);
42 | gateway.getManagedChannel().shutdown();
43 | String tokenString = response.getAccessToken();
44 | long expiresAt = response.getExpiresAt();
45 | return new AccessToken(tokenString, new Date(expiresAt));
46 | }
47 |
48 | public static AccessToken submitDelegatedAuth(BrokerServerInfo serverInfo, String sessionToken) {
49 | BrokerGateway gateway = new BrokerGateway(serverInfo);
50 | gateway.setSessionToken(sessionToken);
51 | GetAccessTokenRequest request = GetAccessTokenRequest.newBuilder().build();
52 | GetAccessTokenResponse response = gateway.getStub().getAccessToken(request);
53 | gateway.getManagedChannel().shutdown();
54 | String tokenString = response.getAccessToken();
55 | long expiresAt = response.getExpiresAt();
56 | return new AccessToken(tokenString, new Date(expiresAt));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/endpoints/GetSessionToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.endpoints;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.protobuf.GetSessionTokenRequest;
15 | import com.google.cloud.broker.apps.brokerserver.protobuf.GetSessionTokenResponse;
16 | import com.google.cloud.broker.client.connect.BrokerGateway;
17 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
18 |
19 | public class GetSessionToken {
20 |
21 | public static String submit(
22 | BrokerServerInfo serverInfo,
23 | String owner,
24 | String renewer,
25 | Iterable scopes,
26 | String target) {
27 | BrokerGateway gateway = new BrokerGateway(serverInfo);
28 | try {
29 | gateway.setSPNEGOToken();
30 | } catch (Exception e) {
31 | throw new RuntimeException(
32 | String.format(
33 | "Error while getting SPNEGO token for owner=`%s`, renewer=`%s`, scopes=`%s`, target=`%s`",
34 | owner, renewer, scopes, target),
35 | e);
36 | }
37 | GetSessionTokenRequest request =
38 | GetSessionTokenRequest.newBuilder()
39 | .addAllScopes(scopes)
40 | .setOwner(owner)
41 | .setRenewer(renewer)
42 | .setTarget(target)
43 | .build();
44 | GetSessionTokenResponse response = gateway.getStub().getSessionToken(request);
45 | gateway.getManagedChannel().shutdown();
46 | return response.getSessionToken();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/endpoints/RenewSessionToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.endpoints;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.protobuf.RenewSessionTokenRequest;
15 | import com.google.cloud.broker.apps.brokerserver.protobuf.RenewSessionTokenResponse;
16 | import com.google.cloud.broker.client.connect.BrokerGateway;
17 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
18 |
19 | public class RenewSessionToken {
20 |
21 | public static long submit(BrokerServerInfo serverInfo, String sessionToken) {
22 | BrokerGateway gateway = new BrokerGateway(serverInfo);
23 | gateway.setSPNEGOToken();
24 | RenewSessionTokenRequest request =
25 | RenewSessionTokenRequest.newBuilder().setSessionToken(sessionToken).build();
26 | RenewSessionTokenResponse response = gateway.getStub().renewSessionToken(request);
27 | gateway.getManagedChannel().shutdown();
28 | return response.getExpiresAt();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/utils/GrpcUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.utils;
13 |
14 | import com.google.cloud.broker.apps.brokerserver.protobuf.BrokerGrpc;
15 | import io.grpc.ManagedChannel;
16 | import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
17 | import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
18 | import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
19 | import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;
20 | import java.io.ByteArrayInputStream;
21 | import java.io.InputStream;
22 | import java.util.concurrent.Executors;
23 | import java.util.concurrent.TimeUnit;
24 | import javax.net.ssl.SSLException;
25 |
26 | public class GrpcUtils {
27 |
28 | public static ManagedChannel newManagedChannel(
29 | String brokerHostname, int brokerPort, boolean useTLS, String tlsCertificate) {
30 | // Create the gRPC stub
31 | NettyChannelBuilder channelBuilder = NettyChannelBuilder.forAddress(brokerHostname, brokerPort);
32 | if (!useTLS) {
33 | channelBuilder.usePlaintext();
34 | } else {
35 | SslContextBuilder sslContextBuilder;
36 | if (tlsCertificate == null || tlsCertificate.equals("")) {
37 | sslContextBuilder = GrpcSslContexts.forClient();
38 | } else {
39 | // A certificate is provided, so add it to the stub's build
40 | InputStream inputStream = new ByteArrayInputStream(tlsCertificate.getBytes());
41 | try {
42 | sslContextBuilder = GrpcSslContexts.forClient().trustManager(inputStream);
43 | } catch (IllegalArgumentException e) {
44 | throw new IllegalArgumentException(
45 | "The provided certificate for the broker service is invalid");
46 | }
47 | }
48 | try {
49 | SslContext sslContext = sslContextBuilder.build();
50 | channelBuilder.sslContext(sslContext);
51 | } catch (SSLException e) {
52 | throw new RuntimeException(e);
53 | }
54 | }
55 | return channelBuilder.executor(Executors.newSingleThreadExecutor()).build();
56 | }
57 |
58 | public static BrokerGrpc.BrokerBlockingStub newStub(ManagedChannel managedChannel) {
59 | int DEADLINE_MILLISECONDS = 20 * 1000; // Timeout for RPC calls
60 | return BrokerGrpc.newBlockingStub(managedChannel)
61 | .withDeadlineAfter(DEADLINE_MILLISECONDS, TimeUnit.MILLISECONDS);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/utils/OAuthUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.utils;
13 |
14 | import com.google.auth.oauth2.GoogleCredentials;
15 | import com.google.auth.oauth2.IdTokenCredentials;
16 | import com.google.auth.oauth2.IdTokenProvider;
17 | import java.io.IOException;
18 |
19 | public class OAuthUtils {
20 |
21 | public static GoogleCredentials getApplicationDefaultCredentials() {
22 | GoogleCredentials credentials;
23 | try {
24 | credentials = GoogleCredentials.getApplicationDefault();
25 | if (!(credentials instanceof IdTokenProvider)) {
26 | throw new IllegalArgumentException("Credentials are not an instance of IdTokenProvider.");
27 | }
28 | return credentials;
29 | } catch (IOException e) {
30 | throw new RuntimeException(e);
31 | }
32 | }
33 |
34 | public static com.google.auth.oauth2.AccessToken getApplicationDefaultIdToken(String audience) {
35 | try {
36 | GoogleCredentials credentials = getApplicationDefaultCredentials();
37 | if (!(credentials instanceof IdTokenProvider)) {
38 | throw new IllegalArgumentException("Credentials are not an instance of IdTokenProvider.");
39 | }
40 | IdTokenCredentials tokenCredential =
41 | IdTokenCredentials.newBuilder()
42 | .setIdTokenProvider((IdTokenProvider) credentials)
43 | .setTargetAudience(audience)
44 | .build();
45 | return tokenCredential.refreshAccessToken();
46 | } catch (IOException e) {
47 | throw new RuntimeException(e);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/java/com/google/cloud/broker/client/utils/SpnegoUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.utils;
13 |
14 | import org.ietf.jgss.*;
15 |
16 | public final class SpnegoUtils {
17 |
18 | private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
19 | private static final String KRB5_MECHANISM_OID = "1.2.840.113554.1.2.2";
20 | private static final String KRB5_PRINCIPAL_NAME_OID = "1.2.840.113554.1.2.2.1";
21 |
22 | public static byte[] newSPNEGOToken(String servicePrincipal) throws GSSException {
23 | // Create GSS context for the broker service and the logged-in user
24 | Oid krb5Mechanism = new Oid(KRB5_MECHANISM_OID);
25 | Oid krb5PrincipalNameType = new Oid(KRB5_PRINCIPAL_NAME_OID);
26 | Oid spnegoOid = new Oid(SPNEGO_OID);
27 | GSSManager manager = GSSManager.getInstance();
28 | GSSName gssServerName =
29 | manager.createName(servicePrincipal, krb5PrincipalNameType, krb5Mechanism);
30 | GSSContext gssContext =
31 | manager.createContext(gssServerName, spnegoOid, null, GSSCredential.DEFAULT_LIFETIME);
32 | gssContext.requestMutualAuth(true);
33 | gssContext.requestCredDeleg(true);
34 |
35 | // Generate the SPNEGO token
36 | byte[] token = new byte[0];
37 | token = gssContext.initSecContext(token, 0, token.length);
38 | return token;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/code/client/client-lib/src/main/proto/broker.proto:
--------------------------------------------------------------------------------
1 | ../../../../../broker-server/src/main/proto/broker.proto
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/main/java/com/google/cloud/broker/client/hadoop/fs/BrokerDelegationTokenBinding.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.hadoop.fs;
13 |
14 | import com.google.cloud.hadoop.fs.gcs.auth.AbstractDelegationTokenBinding;
15 | import com.google.cloud.hadoop.util.AccessTokenProvider;
16 | import java.io.IOException;
17 | import org.apache.hadoop.io.Text;
18 | import org.apache.hadoop.security.UserGroupInformation;
19 | import org.apache.hadoop.security.token.delegation.web.DelegationTokenIdentifier;
20 |
21 | public class BrokerDelegationTokenBinding extends AbstractDelegationTokenBinding {
22 |
23 | public BrokerDelegationTokenBinding() {
24 | super(BrokerTokenIdentifier.KIND);
25 | }
26 |
27 | @Override
28 | public AccessTokenProvider deployUnbonded() throws IOException {
29 | return new BrokerAccessTokenProvider(getService());
30 | }
31 |
32 | @Override
33 | public AccessTokenProvider bindToTokenIdentifier(DelegationTokenIdentifier retrievedIdentifier)
34 | throws IOException {
35 | return new BrokerAccessTokenProvider(getService(), (BrokerTokenIdentifier) retrievedIdentifier);
36 | }
37 |
38 | @Override
39 | public DelegationTokenIdentifier createTokenIdentifier() throws IOException {
40 | return createEmptyIdentifier();
41 | }
42 |
43 | @Override
44 | public DelegationTokenIdentifier createTokenIdentifier(Text renewer) throws IOException {
45 | UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
46 | String user = ugi.getUserName();
47 | Text owner = new Text(user);
48 | Text realUser = null;
49 | if (ugi.getRealUser() != null) {
50 | realUser = new Text(ugi.getRealUser().getUserName());
51 | }
52 | return new BrokerTokenIdentifier(
53 | getFileSystem().getConf(), owner, renewer, realUser, getService());
54 | }
55 |
56 | @Override
57 | public DelegationTokenIdentifier createEmptyIdentifier() {
58 | return new BrokerTokenIdentifier();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/main/java/com/google/cloud/broker/client/hadoop/fs/Utils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.hadoop.fs;
13 |
14 | import com.google.cloud.broker.client.connect.BrokerServerInfo;
15 | import org.apache.hadoop.conf.Configuration;
16 | import org.apache.hadoop.io.Text;
17 |
18 | public class Utils {
19 |
20 | public static final String CONFIG_ACCESS_BOUNDARY_ENABLED =
21 | "gcp.token.broker.access.boundary.enabled";
22 | public static final String CONFIG_URI = "gcp.token.broker.uri";
23 | public static final String CONFIG_PRINCIPAL = "gcp.token.broker.kerberos.principal";
24 | public static final String CONFIG_CERTIFICATE = "gcp.token.broker.tls.certificate";
25 | public static final String CONFIG_CERTIFICATE_PATH = "gcp.token.broker.tls.certificate.path";
26 | public static final String CONFIG_USE_APP_DEFAULT_CREDENTIALS =
27 | "gcp.token.broker.use.app.default.credentials";
28 |
29 | public static String getTarget(Configuration config, Text service) {
30 | boolean accessBoundaryEnabled =
31 | Boolean.parseBoolean(config.get(CONFIG_ACCESS_BOUNDARY_ENABLED, "false"));
32 | if (accessBoundaryEnabled) {
33 | String uri = service.toString();
34 | if (uri.startsWith("gs://")) {
35 | uri = "//storage.googleapis.com/projects/_/buckets/" + uri.substring(5);
36 | }
37 | return uri;
38 | } else {
39 | return "";
40 | }
41 | }
42 |
43 | public static BrokerServerInfo getBrokerDetailsFromConfig(Configuration config) {
44 | return new BrokerServerInfo(
45 | config.get(CONFIG_URI),
46 | config.get(CONFIG_PRINCIPAL),
47 | config.get(CONFIG_CERTIFICATE),
48 | config.get(CONFIG_CERTIFICATE_PATH));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/main/java/com/google/cloud/broker/client/hadoop/fs/commands/CancelSessionToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.hadoop.fs.commands;
13 |
14 | import com.google.cloud.broker.client.hadoop.fs.BrokerTokenIdentifier;
15 | import com.google.cloud.broker.client.hadoop.fs.BrokerTokenRenewer;
16 | import java.io.IOException;
17 | import org.apache.hadoop.conf.Configuration;
18 | import org.apache.hadoop.io.Text;
19 | import org.apache.hadoop.security.token.Token;
20 | import picocli.CommandLine;
21 | import picocli.CommandLine.Command;
22 | import picocli.CommandLine.Option;
23 |
24 | @Command(name = "CancelSessionToken", description = "Retrieves an Oauth2 access token")
25 | public class CancelSessionToken implements Runnable {
26 |
27 | @Option(
28 | names = {"-u", "--uri"},
29 | required = true,
30 | description = "GCS URI for the access token")
31 | private String uri;
32 |
33 | @Option(
34 | names = {"-f", "--session-token-file"},
35 | required = true,
36 | description = "File that contains the session token to be canceled")
37 | private String file;
38 |
39 | @Option(
40 | names = {"-h", "--help"},
41 | usageHelp = true,
42 | description = "Display this help")
43 | boolean help;
44 |
45 | private void sendRequest(Configuration config, String sessionToken) {
46 | String bucket = CommandUtils.extractBucketNameFromGcsUri(uri);
47 | Text service = new Text(bucket);
48 | Token token = CommandUtils.getTokenBTI(sessionToken, service);
49 | BrokerTokenRenewer renewer = new BrokerTokenRenewer();
50 | try {
51 | renewer.cancel(token, config);
52 | } catch (IOException e) {
53 | throw new RuntimeException(e);
54 | }
55 | System.out.println("\n> Session token successfully canceled\n");
56 | }
57 |
58 | @Override
59 | public void run() {
60 | Configuration config = new Configuration();
61 | CommandUtils.showConfig(config);
62 | String sessionToken = CommandUtils.readSessionToken(file);
63 | sendRequest(config, sessionToken);
64 | }
65 |
66 | public static void main(String[] args) {
67 | CommandLine.run(new CancelSessionToken(), args);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/main/java/com/google/cloud/broker/client/hadoop/fs/commands/RenewSessionToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.hadoop.fs.commands;
13 |
14 | import com.google.cloud.broker.client.hadoop.fs.BrokerTokenIdentifier;
15 | import com.google.cloud.broker.client.hadoop.fs.BrokerTokenRenewer;
16 | import java.io.IOException;
17 | import org.apache.hadoop.conf.Configuration;
18 | import org.apache.hadoop.io.Text;
19 | import org.apache.hadoop.security.token.Token;
20 | import picocli.CommandLine;
21 | import picocli.CommandLine.Command;
22 | import picocli.CommandLine.Option;
23 |
24 | @Command(name = "RenewSessionToken", description = "Retrieves an Oauth2 access token")
25 | public class RenewSessionToken implements Runnable {
26 |
27 | @Option(
28 | names = {"-u", "--uri"},
29 | required = true,
30 | description = "GCS URI for the access token")
31 | private String uri;
32 |
33 | @Option(
34 | names = {"-f", "--session-token-file"},
35 | required = true,
36 | description = "File that contains the session token to be renewed")
37 | private String file;
38 |
39 | @Option(
40 | names = {"-h", "--help"},
41 | usageHelp = true,
42 | description = "Display this help")
43 | boolean help;
44 |
45 | private void sendRequest(Configuration config, String sessionToken) {
46 | String bucket = CommandUtils.extractBucketNameFromGcsUri(uri);
47 | Text service = new Text(bucket);
48 | Token token = CommandUtils.getTokenBTI(sessionToken, service);
49 | BrokerTokenRenewer renewer = new BrokerTokenRenewer();
50 | try {
51 | renewer.renew(token, config);
52 | } catch (IOException e) {
53 | throw new RuntimeException(e);
54 | }
55 | System.out.println("\n> Session token successfully renewed\n");
56 | }
57 |
58 | @Override
59 | public void run() {
60 | Configuration config = new Configuration();
61 | CommandUtils.showConfig(config);
62 | String sessionToken = CommandUtils.readSessionToken(file);
63 | sendRequest(config, sessionToken);
64 | }
65 |
66 | public static void main(String[] args) {
67 | CommandLine.run(new RenewSessionToken(), args);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/main/resources/META-INF/services/org.apache.hadoop.security.token.TokenIdentifier:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | com.google.cloud.broker.client.hadoop.fs.BrokerTokenIdentifier
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/main/resources/META-INF/services/org.apache.hadoop.security.token.TokenRenewer:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | com.google.cloud.broker.client.hadoop.fs.BrokerTokenRenewer
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/test/java/com/google/cloud/broker/client/hadoop/fs/BrokerDelegationTokenBindingTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.hadoop.fs;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import java.io.IOException;
17 | import org.junit.Test;
18 |
19 | public class BrokerDelegationTokenBindingTest {
20 |
21 | @Test
22 | public void testDeployUnbonded() {
23 | BrokerDelegationTokenBinding binding = new BrokerDelegationTokenBinding();
24 | try {
25 | BrokerAccessTokenProvider provider = (BrokerAccessTokenProvider) binding.deployUnbonded();
26 | // TODO...
27 | } catch (IOException e) {
28 | fail();
29 | }
30 | }
31 |
32 | @Test
33 | public void testCreateTokenIdentifier() {
34 | BrokerDelegationTokenBinding binding = new BrokerDelegationTokenBinding();
35 | BrokerTokenIdentifier identifier = (BrokerTokenIdentifier) binding.createEmptyIdentifier();
36 | // TODO...
37 | }
38 |
39 | @Test
40 | public void testCreateEmptyIdentifier() {
41 | BrokerDelegationTokenBinding binding = new BrokerDelegationTokenBinding();
42 | try {
43 | BrokerTokenIdentifier identifier = (BrokerTokenIdentifier) binding.createTokenIdentifier();
44 | // TODO...
45 | } catch (IOException e) {
46 | fail();
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/code/client/hadoop-connector/src/test/java/com/google/cloud/broker/client/utils/GrpcUtilsTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.client.utils;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.apps.brokerserver.protobuf.BrokerGrpc;
17 | import io.grpc.ManagedChannel;
18 | import io.grpc.internal.testing.TestUtils;
19 | import java.io.IOException;
20 | import java.security.cert.CertificateException;
21 | import java.security.cert.X509Certificate;
22 | import java.util.Base64;
23 | import org.junit.Test;
24 |
25 | public class GrpcUtilsTest {
26 |
27 | @Test
28 | public void testManagedChannelAuthority() {
29 | ManagedChannel channel = GrpcUtils.newManagedChannel("testhost", 8888, false, null);
30 | assertEquals("testhost:8888", channel.authority());
31 | }
32 |
33 | @Test
34 | public void testManagedChannelTLSSuccess() {
35 | String certificate;
36 | try {
37 | X509Certificate[] trustedCaCerts = {TestUtils.loadX509Cert("ca.pem")};
38 | certificate =
39 | "-----BEGIN CERTIFICATE-----\n"
40 | + Base64.getEncoder().encodeToString(trustedCaCerts[0].getEncoded())
41 | + "\n"
42 | + "-----END CERTIFICATE-----";
43 | } catch (CertificateException | IOException e) {
44 | throw new RuntimeException(e);
45 | }
46 | ManagedChannel channel = GrpcUtils.newManagedChannel("testhost", 8888, true, certificate);
47 | // TODO: Verify that the certificate is correctly assigned to the channel
48 | }
49 |
50 | @Test
51 | public void testManagedChannelTLSInvalidCertificate() {
52 | try {
53 | GrpcUtils.newManagedChannel("testhost", 8888, true, "aaaa");
54 | fail();
55 | } catch (IllegalArgumentException e) {
56 | assertEquals("The provided certificate for the broker service is invalid", e.getMessage());
57 | }
58 | }
59 |
60 | @Test
61 | public void testNewStub() {
62 | ManagedChannel channel = GrpcUtils.newManagedChannel("testhost", 8888, false, null);
63 | BrokerGrpc.BrokerBlockingStub stub = GrpcUtils.newStub(channel);
64 | assertEquals(channel, stub.getChannel());
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/authentication/AuthorizationHeaderServerInterceptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.authentication;
13 |
14 | import io.grpc.*;
15 |
16 | public class AuthorizationHeaderServerInterceptor implements ServerInterceptor {
17 |
18 | private static final Metadata.Key BROKER_AUTHORIZATION_METADATA_KEY =
19 | Metadata.Key.of("broker-authorization", Metadata.ASCII_STRING_MARSHALLER);
20 | public static final Context.Key BROKER_AUTHORIZATION_CONTEXT_KEY =
21 | Context.key("BrokerAuthorizationHeader");
22 |
23 | @Override
24 | public ServerCall.Listener interceptCall(
25 | ServerCall serverCall,
26 | Metadata metadata,
27 | ServerCallHandler serverCallHandler) {
28 | String authorizationHeader = metadata.get(BROKER_AUTHORIZATION_METADATA_KEY);
29 | Context ctx =
30 | Context.current().withValue(BROKER_AUTHORIZATION_CONTEXT_KEY, authorizationHeader);
31 | return Contexts.interceptCall(ctx, serverCall, metadata, serverCallHandler);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/authentication/backends/AbstractAuthenticationBackend.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.authentication.backends;
13 |
14 | import com.google.cloud.broker.authentication.AuthorizationHeaderServerInterceptor;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.utils.InstanceUtils;
17 | import org.slf4j.MDC;
18 |
19 | public abstract class AbstractAuthenticationBackend {
20 |
21 | private static AbstractAuthenticationBackend instance;
22 | public static final String AUTHENTICATED_USER = "authenticatedUser";
23 |
24 | public static AbstractAuthenticationBackend getInstance() {
25 | String className = AppSettings.getInstance().getString(AppSettings.AUTHENTICATION_BACKEND);
26 | if (instance == null || !className.equals(instance.getClass().getCanonicalName())) {
27 | instance = (AbstractAuthenticationBackend) InstanceUtils.invokeConstructor(className);
28 | }
29 | return instance;
30 | }
31 |
32 | public String authenticateUser() {
33 | String authorizationHeader =
34 | AuthorizationHeaderServerInterceptor.BROKER_AUTHORIZATION_CONTEXT_KEY.get();
35 | String authenticatedUser = authenticateUser(authorizationHeader);
36 | MDC.put(AUTHENTICATED_USER, authenticatedUser);
37 | return authenticatedUser;
38 | }
39 |
40 | public abstract String authenticateUser(String authorizationHeader);
41 | }
42 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/caching/local/LocalCache.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.caching.local;
13 |
14 | import java.util.concurrent.TimeUnit;
15 | import net.jodah.expiringmap.ExpirationPolicy;
16 | import net.jodah.expiringmap.ExpiringMap;
17 |
18 | public class LocalCache {
19 |
20 | private static ExpiringMap cache =
21 | ExpiringMap.builder().variableExpiration().build();
22 |
23 | public static Object get(String key) {
24 | return cache.get(key);
25 | }
26 |
27 | public static void set(String key, Object value) {
28 | cache.put(key, value);
29 | }
30 |
31 | public static void set(String key, Object value, int expireIn) {
32 | cache.put(key, value, ExpirationPolicy.CREATED, expireIn, TimeUnit.SECONDS);
33 | }
34 |
35 | public static void delete(String key) {
36 | cache.remove(key);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/caching/remote/AbstractRemoteCache.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.caching.remote;
13 |
14 | import com.google.cloud.broker.checks.CheckResult;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.utils.InstanceUtils;
17 | import java.util.concurrent.locks.Lock;
18 |
19 | public abstract class AbstractRemoteCache {
20 |
21 | private static AbstractRemoteCache instance;
22 |
23 | public abstract byte[] get(String key);
24 |
25 | public abstract void set(String key, byte[] value);
26 |
27 | public abstract void set(String key, byte[] value, int expireIn); // "expireIn" in seconds
28 |
29 | public abstract void delete(String key);
30 |
31 | public abstract Lock acquireLock(String lockName);
32 |
33 | public abstract CheckResult checkConnection();
34 |
35 | public static AbstractRemoteCache getInstance() {
36 | String className = AppSettings.getInstance().getString(AppSettings.REMOTE_CACHE);
37 | if (instance == null || !className.equals(instance.getClass().getCanonicalName())) {
38 | instance = (AbstractRemoteCache) InstanceUtils.invokeConstructor(className);
39 | }
40 | return instance;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/caching/remote/DummyCache.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.caching.remote;
13 |
14 | import com.google.cloud.broker.checks.CheckResult;
15 | import java.util.concurrent.TimeUnit;
16 | import java.util.concurrent.locks.Condition;
17 | import java.util.concurrent.locks.Lock;
18 |
19 | /**
20 | * Dummy caching backend that does not actually cache anything. Use only for testing. Do NOT use in
21 | * production!
22 | */
23 | public class DummyCache extends AbstractRemoteCache {
24 |
25 | @Override
26 | public byte[] get(String key) {
27 | return null;
28 | }
29 |
30 | @Override
31 | public void set(String key, byte[] value) {}
32 |
33 | @Override
34 | public void set(String key, byte[] value, int expireIn) {}
35 |
36 | @Override
37 | public void delete(String key) {}
38 |
39 | @Override
40 | public Lock acquireLock(String lockName) {
41 | return new NoOpLock();
42 | }
43 |
44 | @Override
45 | public CheckResult checkConnection() {
46 | return new CheckResult(true);
47 | }
48 |
49 | public static class NoOpLock implements Lock {
50 |
51 | @Override
52 | public void lock() {}
53 |
54 | @Override
55 | public void lockInterruptibly() throws InterruptedException {}
56 |
57 | @Override
58 | public boolean tryLock() {
59 | return true;
60 | }
61 |
62 | @Override
63 | public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
64 | return true;
65 | }
66 |
67 | @Override
68 | public void unlock() {}
69 |
70 | @Override
71 | public Condition newCondition() {
72 | throw new UnsupportedOperationException();
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/checks/CheckResult.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.checks;
13 |
14 | public class CheckResult {
15 |
16 | private boolean success;
17 | private String message;
18 | private String type;
19 |
20 | public CheckResult(boolean success) {
21 | this(success, null);
22 | }
23 |
24 | public CheckResult(boolean success, String message) {
25 | this.success = success;
26 | this.message = message;
27 | }
28 |
29 | public boolean isSuccess() {
30 | return success;
31 | }
32 |
33 | public String getMessage() {
34 | return message;
35 | }
36 |
37 | public String getType() {
38 | return type;
39 | }
40 |
41 | public void setType(String type) {
42 | this.type = type;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/checks/SystemCheck.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.checks;
13 |
14 | import com.google.cloud.broker.caching.remote.AbstractRemoteCache;
15 | import com.google.cloud.broker.database.backends.AbstractDatabaseBackend;
16 | import com.google.cloud.broker.encryption.backends.AbstractEncryptionBackend;
17 | import java.lang.invoke.MethodHandles;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | public class SystemCheck {
24 |
25 | private static final Logger logger =
26 | LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
27 | private static List results = new ArrayList<>();
28 |
29 | public static void runChecks() {
30 | // Check the database connection
31 | CheckResult dbResult = AbstractDatabaseBackend.getInstance().checkConnection();
32 | dbResult.setType("Database backend");
33 | results.add(dbResult);
34 |
35 | // Check the cache connection
36 | CheckResult cacheResult = AbstractRemoteCache.getInstance().checkConnection();
37 | cacheResult.setType("Cache backend");
38 | results.add(cacheResult);
39 |
40 | // Check the encryption backend
41 | CheckResult encryptionResult = AbstractEncryptionBackend.getInstance().checkConnection();
42 | encryptionResult.setType("Encryption backend");
43 | results.add(encryptionResult);
44 |
45 | // Collate all the potential check failures together
46 | StringBuilder sb = new StringBuilder();
47 | for (CheckResult result : results) {
48 | if (!result.isSuccess()) {
49 | sb.append(String.format("* Failure: %s\n\n%s\n\n", result.getType(), result.getMessage()));
50 | }
51 | }
52 |
53 | // Raise exception if any failures were found
54 | if (sb.length() > 0) {
55 | throw new IllegalStateException("System check failures!\n\n" + sb.toString());
56 | }
57 |
58 | logger.info("System checks passed");
59 | }
60 |
61 | public static void main(String[] args) {
62 | runChecks();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/database/DatabaseObjectNotFound.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database;
13 |
14 | public class DatabaseObjectNotFound extends Exception {
15 |
16 | public DatabaseObjectNotFound(String message) {
17 | super(message);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/database/InitializeDatabase.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database;
13 |
14 | import com.google.cloud.broker.database.backends.AbstractDatabaseBackend;
15 |
16 | public class InitializeDatabase {
17 |
18 | public static void main(String[] args) {
19 | AbstractDatabaseBackend.getInstance().initializeDatabase();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/database/backends/AbstractDatabaseBackend.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.backends;
13 |
14 | import com.google.cloud.broker.checks.CheckResult;
15 | import com.google.cloud.broker.database.DatabaseObjectNotFound;
16 | import com.google.cloud.broker.database.models.Model;
17 | import com.google.cloud.broker.settings.AppSettings;
18 | import com.google.cloud.broker.utils.InstanceUtils;
19 | import java.util.List;
20 |
21 | public abstract class AbstractDatabaseBackend {
22 |
23 | private static AbstractDatabaseBackend instance;
24 |
25 | public abstract List getAll(Class modelClass);
26 |
27 | public abstract Model get(Class modelClass, String objectId) throws DatabaseObjectNotFound;
28 |
29 | public abstract void save(Model model);
30 |
31 | public abstract void delete(Model model);
32 |
33 | public int deleteExpiredItems(Class modelClass, String field, Long cutoffTime) {
34 | return deleteExpiredItems(modelClass, field, cutoffTime, null);
35 | }
36 |
37 | public abstract int deleteExpiredItems(
38 | Class modelClass, String field, Long cutoffTime, Integer numItems);
39 |
40 | public abstract void initializeDatabase();
41 |
42 | public abstract CheckResult checkConnection();
43 |
44 | public static AbstractDatabaseBackend getInstance() {
45 | String className = AppSettings.getInstance().getString(AppSettings.DATABASE_BACKEND);
46 | if (instance == null || !className.equals(instance.getClass().getCanonicalName())) {
47 | instance = (AbstractDatabaseBackend) InstanceUtils.invokeConstructor(className);
48 | }
49 | return instance;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/database/models/Model.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.models;
13 |
14 | import java.lang.reflect.InvocationTargetException;
15 | import java.lang.reflect.Method;
16 | import java.util.Map;
17 |
18 | public abstract class Model {
19 |
20 | public abstract Map toMap();
21 |
22 | public abstract void setDBId(String id);
23 |
24 | public abstract String getDBId();
25 |
26 | public static Model fromMap(Class> klass, Map map) {
27 | Method method;
28 | try {
29 | method = klass.getMethod("fromMap", Map.class);
30 | } catch (NoSuchMethodException e) {
31 | throw new RuntimeException(e);
32 | }
33 | try {
34 | return (Model) method.invoke(null, map);
35 | } catch (IllegalAccessException | InvocationTargetException e) {
36 | throw new RuntimeException(e);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/encryption/backends/AbstractEncryptionBackend.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.encryption.backends;
13 |
14 | import com.google.cloud.broker.checks.CheckResult;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.utils.InstanceUtils;
17 |
18 | public abstract class AbstractEncryptionBackend {
19 |
20 | private static AbstractEncryptionBackend instance;
21 |
22 | public abstract byte[] decrypt(byte[] cipherText);
23 |
24 | public abstract byte[] encrypt(byte[] plainText);
25 |
26 | public abstract CheckResult checkConnection();
27 |
28 | public static AbstractEncryptionBackend getInstance() {
29 | String className = AppSettings.getInstance().getString(AppSettings.ENCRYPTION_BACKEND);
30 | if (instance == null || !className.equals(instance.getClass().getCanonicalName())) {
31 | instance = (AbstractEncryptionBackend) InstanceUtils.invokeConstructor(className);
32 | }
33 | return instance;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/encryption/backends/DummyEncryptionBackend.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.encryption.backends;
13 |
14 | import com.google.cloud.broker.checks.CheckResult;
15 |
16 | /**
17 | * Dummy encryption backend that does not encrypt nor decrypt anything. Use only for testing. Do NOT
18 | * use in production!
19 | */
20 | public class DummyEncryptionBackend extends AbstractEncryptionBackend {
21 |
22 | @Override
23 | public byte[] decrypt(byte[] cipherText) {
24 | return cipherText;
25 | }
26 |
27 | @Override
28 | public byte[] encrypt(byte[] plainText) {
29 | return plainText;
30 | }
31 |
32 | @Override
33 | public CheckResult checkConnection() {
34 | return new CheckResult(true);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/oauth/OauthClientSecretsLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.oauth;
18 |
19 | import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
20 | import com.google.api.client.json.JsonFactory;
21 | import com.google.api.client.json.jackson2.JacksonFactory;
22 | import com.google.cloud.broker.settings.AppSettings;
23 | import com.typesafe.config.ConfigException;
24 | import java.io.*;
25 |
26 | public class OauthClientSecretsLoader {
27 |
28 | public static GoogleClientSecrets getSecrets() {
29 | try {
30 | String jsonPath =
31 | AppSettings.getInstance().getString(AppSettings.OAUTH_CLIENT_SECRET_JSON_PATH);
32 | // Load the JSON file if provided
33 | File secretJson = new java.io.File(jsonPath);
34 | JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
35 | try {
36 | InputStream in = new FileInputStream(secretJson);
37 | return GoogleClientSecrets.load(jsonFactory, new InputStreamReader(in));
38 | } catch (IOException e) {
39 | throw new RuntimeException(e);
40 | }
41 | } catch (ConfigException.Missing e) {
42 | // The JSON path setting was not provided, so we try with other settings
43 | try {
44 | String clientId = AppSettings.getInstance().getString(AppSettings.OAUTH_CLIENT_ID);
45 | String clientSecret = AppSettings.getInstance().getString(AppSettings.OAUTH_CLIENT_SECRET);
46 |
47 | // Fall back to using the provided ID and secret
48 | GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
49 | details.setClientId(clientId);
50 | details.setClientSecret(clientSecret);
51 | GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
52 | clientSecrets.setWeb(details);
53 | return clientSecrets;
54 | } catch (ConfigException.Missing ex) {
55 | throw new RuntimeException(
56 | String.format(
57 | "OAuth misconfigured. Please provide settings `%s` or `%s` and `%s`",
58 | AppSettings.OAUTH_CLIENT_SECRET_JSON_PATH,
59 | AppSettings.OAUTH_CLIENT_ID,
60 | AppSettings.OAUTH_CLIENT_SECRET));
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/oauth/RefreshToken.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.oauth;
13 |
14 | import com.fasterxml.jackson.annotation.JsonProperty;
15 | import com.google.cloud.broker.database.models.Model;
16 | import com.google.cloud.broker.utils.TimeUtils;
17 | import java.util.HashMap;
18 | import java.util.Map;
19 |
20 | public class RefreshToken extends Model {
21 |
22 | private String id; // GSuite email address (e.g. alice@example.com)
23 | private byte[] value; // The actual OAuth refresh token (Recommendation: encrypt this value)
24 | private Long creationTime; // The time when the object was created (in milliseconds)
25 |
26 | public RefreshToken(
27 | @JsonProperty("id") String id,
28 | @JsonProperty("value") byte[] value,
29 | @JsonProperty("creationTime") Long creationTime) {
30 | setId(id);
31 | setValue(value);
32 | setCreationTime(
33 | (creationTime == null) ? Long.valueOf(TimeUtils.currentTimeMillis()) : creationTime);
34 | }
35 |
36 | @Override
37 | public Map toMap() {
38 | HashMap map = new HashMap();
39 | map.put("id", id);
40 | map.put("value", value);
41 | map.put("creationTime", creationTime);
42 | return map;
43 | }
44 |
45 | public static Model fromMap(Map map) {
46 | return new RefreshToken(
47 | (String) map.get("id"), (byte[]) map.get("value"), (Long) map.get("creationTime"));
48 | }
49 |
50 | public void setDBId(String id) {
51 | setId(id);
52 | }
53 |
54 | public String getDBId() {
55 | return getId();
56 | }
57 |
58 | public String getId() {
59 | return id;
60 | }
61 |
62 | public void setId(String id) {
63 | this.id = id;
64 | }
65 |
66 | public byte[] getValue() {
67 | return value;
68 | }
69 |
70 | public void setValue(byte[] value) {
71 | this.value = value;
72 | }
73 |
74 | public Long getCreationTime() {
75 | return creationTime;
76 | }
77 |
78 | public void setCreationTime(Long creationTime) {
79 | this.creationTime = creationTime;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/secretmanager/DownloadSecrets.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.secretmanager;
13 |
14 | public class DownloadSecrets {
15 |
16 | public static void main(String[] args) {
17 | SecretManager.downloadSecrets();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/usermapping/AbstractUserMapper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.usermapping;
13 |
14 | import com.google.cloud.broker.settings.AppSettings;
15 | import com.google.cloud.broker.utils.InstanceUtils;
16 |
17 | public abstract class AbstractUserMapper {
18 |
19 | private static AbstractUserMapper instance;
20 |
21 | public static AbstractUserMapper getInstance() {
22 | String className = AppSettings.getInstance().getString(AppSettings.USER_MAPPER);
23 | if (instance == null || !className.equals(instance.getClass().getCanonicalName())) {
24 | instance = (AbstractUserMapper) InstanceUtils.invokeConstructor(className);
25 | }
26 | return instance;
27 | }
28 |
29 | public abstract String map(String name) throws IllegalArgumentException;
30 | }
31 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/usermapping/MapUser.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.usermapping;
13 |
14 | import com.google.cloud.broker.validation.EmailValidation;
15 | import java.lang.invoke.MethodHandles;
16 | import org.slf4j.Logger;
17 | import org.slf4j.LoggerFactory;
18 |
19 | public class MapUser {
20 |
21 | private static final Logger logger =
22 | LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
23 |
24 | public static void main(String[] args) {
25 | if (args.length == 1) {
26 | String email = AbstractUserMapper.getInstance().map(args[0]);
27 | EmailValidation.validateEmail(email);
28 | logger.info(email);
29 | } else {
30 | logger.error("This command requires one argument.");
31 | System.exit(1);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/utils/CloudStorageUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.utils;
18 |
19 | import com.google.auth.oauth2.GoogleCredentials;
20 | import com.google.cloud.storage.Storage;
21 | import com.google.cloud.storage.StorageOptions;
22 | import java.io.IOException;
23 |
24 | public class CloudStorageUtils {
25 |
26 | public static final String GCS_API = "https://www.googleapis.com/auth/devstorage.read_write";
27 |
28 | public static GoogleCredentials getCloudStorageCredentials() {
29 | try {
30 | return GoogleCredentials.getApplicationDefault().createScoped(GCS_API);
31 | } catch (IOException e) {
32 | throw new RuntimeException(e);
33 | }
34 | }
35 |
36 | public static Storage getCloudStorageClient() {
37 | GoogleCredentials credentials = getCloudStorageCredentials();
38 | return getCloudStorageClient(credentials);
39 | }
40 |
41 | public static Storage getCloudStorageClient(GoogleCredentials credentials) {
42 | return StorageOptions.newBuilder().setCredentials(credentials).build().getService();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/utils/Constants.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.utils;
13 |
14 | public class Constants {
15 |
16 | public static final String APPLICATION_NAME = "gcp-token-broker";
17 | }
18 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/utils/InstanceUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.utils;
13 |
14 | import java.lang.reflect.Constructor;
15 | import java.lang.reflect.InvocationTargetException;
16 |
17 | public class InstanceUtils {
18 |
19 | public static Object invokeConstructor(String className) {
20 | try {
21 | Class> c = Class.forName(className);
22 | Constructor> constructor = c.getConstructor();
23 | return constructor.newInstance();
24 | } catch (InvocationTargetException e) {
25 | Throwable cause = e.getCause();
26 | if (cause == null) {
27 | throw new RuntimeException(e);
28 | } else {
29 | throw new RuntimeException(cause);
30 | }
31 | } catch (Exception e) {
32 | throw new RuntimeException(e);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/utils/TimeUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.utils;
13 |
14 | public final class TimeUtils {
15 |
16 | public static long currentTimeMillis() {
17 | return System.currentTimeMillis();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/core/src/main/java/com/google/cloud/broker/validation/EmailValidation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.validation;
18 |
19 | import java.util.regex.Matcher;
20 | import java.util.regex.Pattern;
21 |
22 | public class EmailValidation {
23 |
24 | public static void validateEmail(String email) {
25 | Pattern parser = Pattern.compile("([a-zA-Z0-9\\.-]+)@([a-zA-Z0-9\\.-]+)");
26 | Matcher match = parser.matcher(email);
27 | if (!match.matches()) {
28 | throw new IllegalArgumentException("Invalid email: " + email);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/code/core/src/test/java/com/google/cloud/broker/authentication/backends/AbstractAuthenticationBackendTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.authentication.backends;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.settings.AppSettings;
17 | import com.google.cloud.broker.settings.SettingsOverride;
18 | import java.util.Map;
19 | import org.junit.Test;
20 |
21 | public class AbstractAuthenticationBackendTest {
22 |
23 | @Test
24 | public void testGetInstance() {
25 | try (SettingsOverride override =
26 | SettingsOverride.apply(
27 | Map.of(AppSettings.AUTHENTICATION_BACKEND, "com.example.DoesNotExist"))) {
28 | try {
29 | AbstractAuthenticationBackend.getInstance();
30 | fail();
31 | } catch (RuntimeException e) {
32 | assertEquals("java.lang.ClassNotFoundException: com.example.DoesNotExist", e.getMessage());
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/core/src/test/java/com/google/cloud/broker/caching/remote/AbstractRemoteCacheTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.caching.remote;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.settings.AppSettings;
17 | import com.google.cloud.broker.settings.SettingsOverride;
18 | import java.util.Map;
19 | import org.junit.Test;
20 |
21 | public class AbstractRemoteCacheTest {
22 |
23 | @Test
24 | public void testGetInstance() {
25 | try (SettingsOverride override =
26 | SettingsOverride.apply(Map.of(AppSettings.REMOTE_CACHE, "com.example.DoesNotExist"))) {
27 | try {
28 | AbstractRemoteCache.getInstance();
29 | fail();
30 | } catch (RuntimeException e) {
31 | assertEquals("java.lang.ClassNotFoundException: com.example.DoesNotExist", e.getMessage());
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/code/core/src/test/java/com/google/cloud/broker/database/backends/AbstractDatabaseBackendTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.backends;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.settings.AppSettings;
17 | import com.google.cloud.broker.settings.SettingsOverride;
18 | import java.util.Map;
19 | import org.junit.Test;
20 |
21 | public class AbstractDatabaseBackendTest {
22 |
23 | @Test
24 | public void testGetInstance() {
25 | try (SettingsOverride override =
26 | SettingsOverride.apply(Map.of(AppSettings.DATABASE_BACKEND, "com.example.DoesNotExist"))) {
27 | try {
28 | AbstractDatabaseBackend.getInstance();
29 | fail();
30 | } catch (RuntimeException e) {
31 | assertEquals("java.lang.ClassNotFoundException: com.example.DoesNotExist", e.getMessage());
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/code/core/src/test/java/com/google/cloud/broker/encryption/backends/AbstractEncryptionBackendTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.encryption.backends;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.settings.AppSettings;
17 | import com.google.cloud.broker.settings.SettingsOverride;
18 | import java.util.Map;
19 | import org.junit.Test;
20 |
21 | public class AbstractEncryptionBackendTest {
22 |
23 | @Test
24 | public void testGetInstance() {
25 | try (SettingsOverride override =
26 | SettingsOverride.apply(
27 | Map.of(AppSettings.ENCRYPTION_BACKEND, "com.example.DoesNotExist"))) {
28 | try {
29 | AbstractEncryptionBackend.getInstance();
30 | fail();
31 | } catch (RuntimeException e) {
32 | assertEquals("java.lang.ClassNotFoundException: com.example.DoesNotExist", e.getMessage());
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/core/src/test/java/com/google/cloud/broker/oauth/RefreshTokenTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.oauth;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | import com.google.cloud.broker.database.models.Model;
17 | import java.util.HashMap;
18 | import org.junit.Test;
19 |
20 | public class RefreshTokenTest {
21 |
22 | // TODO: testToMap
23 |
24 | @Test
25 | public void testFromMap() {
26 | HashMap values = new HashMap();
27 | values.put("id", "alice@example.com");
28 | values.put("creationTime", 2222222222222L);
29 | values.put("value", "xyz".getBytes());
30 |
31 | RefreshToken token = (RefreshToken) Model.fromMap(RefreshToken.class, values);
32 | assertEquals("alice@example.com", token.getId());
33 | assertEquals(2222222222222L, token.getCreationTime().longValue());
34 | assertArrayEquals("xyz".getBytes(), token.getValue());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/core/src/test/java/com/google/cloud/broker/settings/SettingsOverride.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.settings;
18 |
19 | import com.typesafe.config.Config;
20 | import com.typesafe.config.ConfigFactory;
21 | import java.util.HashMap;
22 | import java.util.Map;
23 | import org.junit.rules.TestRule;
24 | import org.junit.runner.Description;
25 | import org.junit.runners.model.Statement;
26 |
27 | public class SettingsOverride implements TestRule, AutoCloseable {
28 |
29 | private Map newSettingsMap;
30 | private Config backupConfig;
31 |
32 | public SettingsOverride() {
33 | this(new HashMap<>());
34 | }
35 |
36 | public SettingsOverride(Map newSettingsMap) {
37 | this.newSettingsMap = newSettingsMap;
38 | // Keep a backup of the old settings
39 | backupConfig = AppSettings.getInstance();
40 | }
41 |
42 | /** Called when used as a jUnit Rule. */
43 | @Override
44 | public Statement apply(Statement statement, Description description) {
45 | return new Statement() {
46 | @Override
47 | public void evaluate() throws Throwable {
48 | // Override the settings
49 | override();
50 | try {
51 | // Execute the test
52 | statement.evaluate();
53 | } finally {
54 | // Restore the old settings
55 | restore();
56 | }
57 | }
58 | };
59 | }
60 |
61 | private void override() {
62 | // Replace settings' instance with a new, temporary one
63 | AppSettings.setInstance(
64 | ConfigFactory.parseMap(newSettingsMap).withFallback(AppSettings.getInstance()));
65 | }
66 |
67 | private void restore() {
68 | // Restore the old settings
69 | AppSettings.setInstance(backupConfig);
70 | }
71 |
72 | /** To be used as an AutoCloseable in a try() clause. */
73 | public static SettingsOverride apply(Map newSettingsMap) {
74 | SettingsOverride settingsOverride = new SettingsOverride(newSettingsMap);
75 | settingsOverride.override();
76 | return settingsOverride;
77 | }
78 |
79 | /** Automatically triggered at the end of a try() clause. */
80 | @Override
81 | public void close() {
82 | restore();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/code/extensions/caching/cloud-datastore/src/main/java/com/google/cloud/broker/caching/remote/DatastoreCacheCleanup.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.caching.remote;
13 |
14 | import java.lang.invoke.MethodHandles;
15 | import org.slf4j.Logger;
16 | import org.slf4j.LoggerFactory;
17 |
18 | public class DatastoreCacheCleanup {
19 |
20 | private static final Class> klass = MethodHandles.lookup().lookupClass();
21 | private static final Logger logger = LoggerFactory.getLogger(klass);
22 |
23 | public static void main(String[] args) {
24 | Integer limit = null;
25 | if (args.length > 0) {
26 | limit = Integer.parseInt(args[0]);
27 | }
28 | CloudDatastoreCache cache = new CloudDatastoreCache();
29 | int numDeletedItems = cache.deleteExpiredItems(limit);
30 | logger.info(klass.getSimpleName() + " - Deleted expired item(s): " + numDeletedItems);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/code/extensions/caching/redis/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
18 | 4.0.0
19 |
20 |
21 | com.google.cloud.broker
22 | broker-parent
23 | 0.10.5
24 | ../../../../pom.xml
25 |
26 |
27 | cache-backend-redis
28 |
29 | Redis cache backend for the GCP Token Broker
30 |
31 |
32 |
33 | com.google.cloud.broker
34 | broker-core
35 | ${project.parent.version}
36 | provided
37 |
38 |
39 | org.redisson
40 | redisson
41 | ${org.redisson.version}
42 |
43 |
44 |
45 |
46 | com.google.cloud.broker
47 | broker-core
48 | ${project.parent.version}
49 | test-jar
50 | test
51 |
52 |
53 |
54 |
55 |
56 |
57 | maven-assembly-plugin
58 | ${maven-assembly-plugin.version}
59 |
60 |
61 | package
62 |
63 | single
64 |
65 |
66 |
67 | jar-with-dependencies
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/code/extensions/database/cloud-datastore/src/test/java/com/google/cloud/broker/database/backends/Foo.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.backends;
13 |
14 | import com.fasterxml.jackson.annotation.JsonProperty;
15 | import com.google.cloud.broker.database.models.Model;
16 | import com.google.common.collect.ImmutableList;
17 | import java.util.HashMap;
18 | import java.util.List;
19 | import java.util.Map;
20 |
21 | public class Foo extends Model {
22 |
23 | private String id;
24 | private byte[] byteVal;
25 | private Long longVal;
26 | private List stringList;
27 |
28 | public Foo(
29 | @JsonProperty("id") String id,
30 | @JsonProperty("byteVal") byte[] byteVal,
31 | @JsonProperty("longVal") Long longVal,
32 | @JsonProperty("longVal") List stringList) {
33 | setId(id);
34 | setByteVal(byteVal);
35 | setLongVal(longVal);
36 | setStringList(stringList);
37 | }
38 |
39 | @Override
40 | public Map toMap() {
41 | HashMap map = new HashMap();
42 | map.put("id", id);
43 | map.put("byteVal", byteVal);
44 | map.put("longVal", longVal);
45 | map.put("stringList", stringList);
46 | return map;
47 | }
48 |
49 | public static Model fromMap(Map map) {
50 | return new Foo(
51 | (String) map.get("id"),
52 | (byte[]) map.get("byteVal"),
53 | (Long) map.get("longVal"),
54 | (List) map.get("stringList"));
55 | }
56 |
57 | public void setDBId(String id) {
58 | setId(id);
59 | }
60 |
61 | public String getDBId() {
62 | return getId();
63 | }
64 |
65 | public String getId() {
66 | return id;
67 | }
68 |
69 | public void setId(String id) {
70 | this.id = id;
71 | }
72 |
73 | public byte[] getByteVal() {
74 | return byteVal;
75 | }
76 |
77 | public void setByteVal(byte[] byteVal) {
78 | this.byteVal = byteVal;
79 | }
80 |
81 | public Long getLongVal() {
82 | return longVal;
83 | }
84 |
85 | public void setLongVal(Long longVal) {
86 | this.longVal = longVal;
87 | }
88 |
89 | public List getStringList() {
90 | return stringList;
91 | }
92 |
93 | public void setStringList(List stringList) {
94 | this.stringList = ImmutableList.copyOf(stringList);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/code/extensions/database/jdbc/src/test/java/com/google/cloud/broker/database/backends/MariaDBBackendTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.backends;
13 |
14 | import com.google.cloud.broker.database.DatabaseObjectNotFound;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.settings.SettingsOverride;
17 | import java.util.Map;
18 | import org.junit.*;
19 |
20 | public class MariaDBBackendTest extends JDBCBackendTest {
21 |
22 | private static JDBCBackend backend;
23 |
24 | @ClassRule
25 | public static SettingsOverride settingsOverride =
26 | new SettingsOverride(
27 | Map.of(
28 | AppSettings.DATABASE_JDBC_URL,
29 | "jdbc:mariadb://localhost:3306/broker?user=testuser&password=UNSECURE-PASSWORD"));
30 |
31 | @BeforeClass
32 | public static void setupClass() {
33 | backend = new JDBCBackend();
34 | }
35 |
36 | @Before
37 | public void setup() {
38 | JDBCBackendTest.setup(backend);
39 | }
40 |
41 | @After
42 | public void teardown() {
43 | JDBCBackendTest.teardown(backend);
44 | }
45 |
46 | @Test
47 | public void testInitializeDatabase() {
48 | JDBCBackendTest.initializeDatabase(backend);
49 | }
50 |
51 | @Test
52 | public void testSaveNew() {
53 | JDBCBackendTest.saveNew(backend);
54 | }
55 |
56 | @Test
57 | public void testUpdate() {
58 | JDBCBackendTest.update(backend);
59 | }
60 |
61 | @Test
62 | public void testSaveWithoutID() {
63 | JDBCBackendTest.saveWithoutID(backend);
64 | }
65 |
66 | @Test
67 | public void testGet() throws DatabaseObjectNotFound {
68 | JDBCBackendTest.get(backend);
69 | }
70 |
71 | @Test
72 | public void testGetNotExist() {
73 | JDBCBackendTest.getNotExist(backend);
74 | }
75 |
76 | @Test
77 | public void testDelete() {
78 | JDBCBackendTest.delete(backend);
79 | }
80 |
81 | @Test
82 | public void testDeleteExpiredItems() {
83 | JDBCBackendTest.deleteExpiredItems(backend, false);
84 | }
85 |
86 | @Test
87 | public void testDeleteExpiredItemsWithLimit() {
88 | JDBCBackendTest.deleteExpiredItems(backend, true);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/code/extensions/database/jdbc/src/test/java/com/google/cloud/broker/database/backends/PostgreSQLBackendTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.backends;
13 |
14 | import com.google.cloud.broker.database.DatabaseObjectNotFound;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.settings.SettingsOverride;
17 | import java.util.Map;
18 | import org.junit.*;
19 |
20 | public class PostgreSQLBackendTest extends JDBCBackendTest {
21 |
22 | private static JDBCBackend backend;
23 |
24 | @ClassRule
25 | public static SettingsOverride settingsOverride =
26 | new SettingsOverride(
27 | Map.of(
28 | AppSettings.DATABASE_JDBC_URL,
29 | "jdbc:postgresql:broker?user=testuser&password=UNSECURE-PASSWORD"));
30 |
31 | @BeforeClass
32 | public static void setupClass() {
33 | backend = new JDBCBackend();
34 | }
35 |
36 | @Before
37 | public void setup() {
38 | JDBCBackendTest.setup(backend);
39 | }
40 |
41 | @After
42 | public void teardown() {
43 | JDBCBackendTest.teardown(backend);
44 | }
45 |
46 | @Test
47 | public void testInitializeDatabase() {
48 | JDBCBackendTest.initializeDatabase(backend);
49 | }
50 |
51 | @Test
52 | public void testSaveNew() {
53 | JDBCBackendTest.saveNew(backend);
54 | }
55 |
56 | @Test
57 | public void testUpdate() {
58 | JDBCBackendTest.update(backend);
59 | }
60 |
61 | @Test
62 | public void testSaveWithoutID() {
63 | JDBCBackendTest.saveWithoutID(backend);
64 | }
65 |
66 | @Test
67 | public void testGet() throws DatabaseObjectNotFound {
68 | JDBCBackendTest.get(backend);
69 | }
70 |
71 | @Test
72 | public void testGetNotExist() {
73 | JDBCBackendTest.getNotExist(backend);
74 | }
75 |
76 | @Test
77 | public void testDelete() {
78 | JDBCBackendTest.delete(backend);
79 | }
80 |
81 | @Test
82 | public void testDeleteExpiredItems() {
83 | JDBCBackendTest.deleteExpiredItems(backend, false);
84 | }
85 |
86 | @Test
87 | public void testDeleteExpiredItemsWithLimit() {
88 | JDBCBackendTest.deleteExpiredItems(backend, true);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/code/extensions/database/jdbc/src/test/java/com/google/cloud/broker/database/backends/SQLiteBackendTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | // Unless required by applicable law or agreed to in writing, software
7 | // distributed under the License is distributed on an "AS IS" BASIS,
8 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | // See the License for the specific language governing permissions and
10 | // limitations under the License.
11 |
12 | package com.google.cloud.broker.database.backends;
13 |
14 | import com.google.cloud.broker.database.DatabaseObjectNotFound;
15 | import com.google.cloud.broker.settings.AppSettings;
16 | import com.google.cloud.broker.settings.SettingsOverride;
17 | import java.util.Map;
18 | import org.junit.*;
19 |
20 | public class SQLiteBackendTest extends JDBCBackendTest {
21 |
22 | private static JDBCBackend backend;
23 |
24 | @ClassRule
25 | public static SettingsOverride settingsOverride =
26 | new SettingsOverride(Map.of(AppSettings.DATABASE_JDBC_URL, "jdbc:sqlite::memory:"));
27 |
28 | @BeforeClass
29 | public static void setupClass() {
30 | backend = new JDBCBackend();
31 | }
32 |
33 | @Before
34 | public void setup() {
35 | JDBCBackendTest.setup(backend);
36 | }
37 |
38 | @After
39 | public void teardown() {
40 | JDBCBackendTest.teardown(backend);
41 | }
42 |
43 | @Test
44 | public void testInitializeDatabase() {
45 | JDBCBackendTest.initializeDatabase(backend);
46 | }
47 |
48 | @Test
49 | public void testSaveNew() {
50 | JDBCBackendTest.saveNew(backend);
51 | }
52 |
53 | @Test
54 | public void testUpdate() {
55 | JDBCBackendTest.update(backend);
56 | }
57 |
58 | @Test
59 | public void testSaveWithoutID() {
60 | JDBCBackendTest.saveWithoutID(backend);
61 | }
62 |
63 | @Test
64 | public void testGet() throws DatabaseObjectNotFound {
65 | JDBCBackendTest.get(backend);
66 | }
67 |
68 | @Test
69 | public void testGetNotExist() {
70 | JDBCBackendTest.getNotExist(backend);
71 | }
72 |
73 | @Test
74 | public void testDelete() {
75 | JDBCBackendTest.delete(backend);
76 | }
77 |
78 | @Test
79 | public void testDeleteExpiredItems() {
80 | JDBCBackendTest.deleteExpiredItems(backend, false);
81 | }
82 |
83 | @Test
84 | public void testDeleteExpiredItemsWithLimit() {
85 | JDBCBackendTest.deleteExpiredItems(backend, true);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/code/extensions/encryption/cloud-kms/src/main/java/com/google/cloud/broker/encryption/GenerateDEK.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.encryption;
18 |
19 | import com.google.cloud.broker.encryption.backends.CloudKMSBackend;
20 | import com.google.cloud.broker.settings.AppSettings;
21 | import java.lang.invoke.MethodHandles;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 |
25 | /** Command-line utility that generates a new data encryption key (DEK) and stores it in GCS */
26 | public class GenerateDEK {
27 |
28 | private static final Logger logger =
29 | LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
30 |
31 | public static void main(String[] args) {
32 | String dekUri = null;
33 | String kekUri = null;
34 | if (args.length == 0) {
35 | dekUri = AppSettings.getInstance().getString(AppSettings.ENCRYPTION_DEK_URI);
36 | kekUri = AppSettings.getInstance().getString(AppSettings.ENCRYPTION_KEK_URI);
37 | } else if (args.length == 2) {
38 | dekUri = args[0];
39 | kekUri = args[1];
40 | } else {
41 | logger.error("Invalid parameters");
42 | System.exit(1);
43 | }
44 |
45 | logger.info("Generating DEK...");
46 | logger.info("Wrapping with KEK `" + kekUri + "`...");
47 | logger.info("Writing to `" + dekUri + "`...");
48 | try {
49 | CloudKMSBackend.generateAndWriteKeyset(dekUri, kekUri);
50 | } catch (Exception e) {
51 | logger.error("Failed to generate and write DEK");
52 | e.printStackTrace(System.err);
53 | System.exit(1);
54 | }
55 | logger.info("Done.");
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/code/extensions/encryption/cloud-kms/src/main/java/com/google/cloud/broker/encryption/backends/keyset/CloudStorageKeysetManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.encryption.backends.keyset;
18 |
19 | import com.google.cloud.WriteChannel;
20 | import com.google.cloud.broker.utils.CloudStorageUtils;
21 | import com.google.cloud.storage.BlobId;
22 | import com.google.cloud.storage.BlobInfo;
23 | import com.google.crypto.tink.JsonKeysetReader;
24 | import com.google.crypto.tink.JsonKeysetWriter;
25 | import com.google.crypto.tink.proto.EncryptedKeyset;
26 | import com.google.crypto.tink.proto.Keyset;
27 | import java.io.IOException;
28 | import java.io.OutputStream;
29 | import java.net.URI;
30 | import java.net.URISyntaxException;
31 | import java.nio.channels.Channels;
32 |
33 | /** KeysetManager that reads and writes DEKs from Cloud Storage. */
34 | public class CloudStorageKeysetManager extends KeysetManager {
35 |
36 | private URI dekUri;
37 |
38 | CloudStorageKeysetManager(String dekUri) {
39 | try {
40 | this.dekUri = new URI(dekUri);
41 | } catch (URISyntaxException e) {
42 | throw new RuntimeException(e);
43 | }
44 | }
45 |
46 | @Override
47 | public Keyset read() throws IOException {
48 | throw new UnsupportedOperationException();
49 | }
50 |
51 | @Override
52 | public EncryptedKeyset readEncrypted() throws IOException {
53 | BlobId blobId = BlobId.of(dekUri.getAuthority(), dekUri.getPath().substring(1));
54 | return JsonKeysetReader.withBytes(
55 | CloudStorageUtils.getCloudStorageClient().readAllBytes(blobId))
56 | .readEncrypted();
57 | }
58 |
59 | @Override
60 | public void write(Keyset keyset) throws IOException {
61 | throw new UnsupportedOperationException();
62 | }
63 |
64 | @Override
65 | public void write(EncryptedKeyset keyset) throws IOException {
66 | BlobId blobId = BlobId.of(dekUri.getAuthority(), dekUri.getPath().substring(1));
67 | WriteChannel wc =
68 | CloudStorageUtils.getCloudStorageClient().writer(BlobInfo.newBuilder(blobId).build());
69 | OutputStream os = Channels.newOutputStream(wc);
70 | JsonKeysetWriter.withOutputStream(os).write(keyset);
71 | os.close();
72 | wc.close();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/code/extensions/encryption/cloud-kms/src/main/java/com/google/cloud/broker/encryption/backends/keyset/FilesystemKeysetManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.encryption.backends.keyset;
18 |
19 | import com.google.crypto.tink.JsonKeysetReader;
20 | import com.google.crypto.tink.JsonKeysetWriter;
21 | import com.google.crypto.tink.proto.EncryptedKeyset;
22 | import com.google.crypto.tink.proto.Keyset;
23 | import java.io.IOException;
24 | import java.nio.file.Path;
25 | import java.nio.file.Paths;
26 |
27 | /** KeysetManager that reads and writes DEKs from the local filesystem. */
28 | public class FilesystemKeysetManager extends KeysetManager {
29 |
30 | private Path dekUri;
31 |
32 | FilesystemKeysetManager(String dekUri) {
33 | this.dekUri = Paths.get(dekUri);
34 | }
35 |
36 | @Override
37 | public Keyset read() throws IOException {
38 | throw new UnsupportedOperationException();
39 | }
40 |
41 | @Override
42 | public EncryptedKeyset readEncrypted() throws IOException {
43 | return JsonKeysetReader.withPath(dekUri).readEncrypted();
44 | }
45 |
46 | @Override
47 | public void write(Keyset keyset) throws IOException {
48 | throw new UnsupportedOperationException();
49 | }
50 |
51 | @Override
52 | public void write(EncryptedKeyset keyset) throws IOException {
53 | JsonKeysetWriter.withPath(dekUri).write(keyset);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/code/extensions/encryption/cloud-kms/src/main/java/com/google/cloud/broker/encryption/backends/keyset/KeysetManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.encryption.backends.keyset;
18 |
19 | import com.google.crypto.tink.KeysetReader;
20 | import com.google.crypto.tink.KeysetWriter;
21 |
22 | public abstract class KeysetManager implements KeysetWriter, KeysetReader {}
23 |
--------------------------------------------------------------------------------
/code/extensions/encryption/cloud-kms/src/main/java/com/google/cloud/broker/encryption/backends/keyset/KeysetUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.encryption.backends.keyset;
18 |
19 | public class KeysetUtils {
20 |
21 | public static KeysetManager getKeysetManager(String dekUri) {
22 | if (dekUri.startsWith("gs://")) {
23 | return new CloudStorageKeysetManager(dekUri);
24 | } else if (dekUri.startsWith("file://")) {
25 | return new FilesystemKeysetManager(dekUri.substring(7));
26 | } else {
27 | throw new RuntimeException("Invalid DEK URI: " + dekUri);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/code/extensions/encryption/cloud-kms/src/test/java/com/google/cloud/broker/encryption/backends/CloudKMSBackendTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.broker.encryption.backends;
18 |
19 | import static org.junit.Assert.*;
20 |
21 | import com.google.cloud.broker.settings.AppSettings;
22 | import com.google.cloud.broker.settings.SettingsOverride;
23 | import java.util.Arrays;
24 | import java.util.Map;
25 | import org.junit.ClassRule;
26 | import org.junit.Test;
27 |
28 | public class CloudKMSBackendTest {
29 |
30 | private static String projectId = AppSettings.getInstance().getString(AppSettings.GCP_PROJECT);
31 |
32 | @ClassRule
33 | public static SettingsOverride settingsOverride =
34 | new SettingsOverride(
35 | Map.of(
36 | AppSettings.ENCRYPTION_KEK_URI,
37 | "projects/"
38 | + projectId
39 | + "/locations/global/keyRings/testkeyring/cryptoKeys/testkey",
40 | AppSettings.ENCRYPTION_DEK_URI, "gs://" + projectId + "-testbucket/testkey.json"));
41 |
42 | /** Encryption backend shall encrypt and correctly decrypt a given plaintext */
43 | @Test
44 | public void testEncryptAndDecrypt() {
45 | CloudKMSBackend aead = new CloudKMSBackend();
46 | byte[] plainText = "test string".getBytes();
47 | byte[] cipherText = aead.encrypt(plainText);
48 | assertFalse(Arrays.equals(plainText, cipherText));
49 | byte[] decrypted = aead.decrypt(cipherText);
50 | assertArrayEquals(plainText, decrypted);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/docs/concepts/authorizer.md:
--------------------------------------------------------------------------------
1 | # Authorizer
2 |
3 | The Authorizer is a Web UI that walks users through an OAuth 2.0 flow to collect OAuth refresh tokens.
4 |
5 | It is necessary for your users to use the Authorizer if you choose to use the [`RefreshTokenProvider`](providers.md#refresh-token-provider).
6 |
7 | When users complete the OAuth flow, the Authorizer obtains a refresh token, [encrypts](encryption.md) it,
8 | and stores it in the [database](database.md). At that point the user is fully authorized to use the broker service.
9 | It is only necessary for each user to go through the flow once.
10 |
11 | The Authorizer application serves three endpoints:
12 |
13 | - `/`: Landing page for the Authorizer app.
14 | - `/google/login`: Redirects the user to the Google login page.
15 | - `/google/oauth2callback`: Receives the OAuth 2.0 authorization code from Google, then uses it to
16 | obtain a refresh token for the authenticated Google user. The refresh token is then encrypted
17 | and stored in the database.
18 |
19 | ## Running the Authorizer
20 |
21 | To run the Authorizer:
22 |
23 | 1. Retrieve the JAR file for the Authorizer package from [Maven Central](https://search.maven.org/search?q=g:com.google.cloud.broker%20AND%20a:authorizer):
24 | ```xml
25 | com.google.cloud.broker
26 | authorizer
27 | ```
28 | 2. Retrieve all the JAR files from Maven Central for the [encryption backend](encryption.md#encryption-backends) and
29 | [database backend](database.md#database-backends)) that you wish to use for your deployment.
30 | 3. Place all the JAR files in the `CLASSPATH`.
31 | 4. Create an `application.conf` file with the [settings](settings.md) for your environment.
32 | 5. [Initialize the database](database.md#database-initialization).
33 | 6. Run the following command:
34 |
35 | ```shell
36 | CONFIG_FILE=//application.conf java com.google.cloud.broker.apps.authorizer.Authorizer
37 | ```
38 |
--------------------------------------------------------------------------------
/docs/concepts/broker-server.md:
--------------------------------------------------------------------------------
1 | # Broker server
2 |
3 | The broker server is the core component of the broker architecture. It accepts [gRPC](https://grpc.io/) requests from
4 | clients and serves four different endpoints:
5 |
6 | - `GetAccessToken`: Returns a GCP access token. Can be called either using [direct authentication](authentication.md#direct-authentication),
7 | [delegated authentication](authentication.md#delegated-authentication), or [proxy user impersonation](authentication.md#proxy-user-impersonation).
8 | - `GetSessionToken`: Called by a user client to create a new [session](sessions.md).
9 | Requires [direct authentication](authentication.md#direct-authentication) or [proxy user impersonation](authentication.md#proxy-user-impersonation).
10 | - `RenewSessionToken`: Called by a [session](sessions.md) renewer to extend the lifetime of a session during the
11 | execution of a job. Requires [direct authentication](authentication.md#direct-authentication).
12 | - `CancelSessionToken`: Called by a [session](sessions.md) renewer to terminate a session at the end of a job.
13 | Requires [direct authentication](authentication.md#direct-authentication).
14 |
15 | ## Running the server
16 |
17 | To run the server:
18 |
19 | 1. Retrieve the JAR file for the broker server package from [Maven Central](https://search.maven.org/search?q=g:com.google.cloud.broker%20AND%20a:broker):
20 | ```xml
21 | com.google.cloud.broker
22 | broker-server
23 | ```
24 | 2. Retrieve all the JAR files from Maven Central for the broker extensions (i.e. the [encryption backend](encryption.md#encryption-backends),
25 | [database backend](database.md#database-backends), [remote cache backends](caching.md#remote-cache-backends))
26 | that you wish to use for your deployment.
27 | 3. Place all the JAR files in the `CLASSPATH`.
28 | 4. Create an `application.conf` file with the [settings](settings.md) for your environment.
29 | 5. [Initialize the database](database.md#database-initialization).
30 | 6. Run the following command:
31 | ```shell
32 | CONFIG_FILE=//application.conf java com.google.cloud.broker.apps.brokerserver.BrokerServer
33 | ```
34 |
--------------------------------------------------------------------------------
/docs/concepts/connector.md:
--------------------------------------------------------------------------------
1 | # Broker connector
2 |
3 | The broker connector is an extension for the [GCS Connector](https://github.com/GoogleCloudPlatform/bigdata-interop/tree/master/gcs),
4 | which acts as an interface between Hadoop and [Cloud Storage](https://cloud.google.com/storage/).
5 |
6 | The broker connector is used by the GCS Connector to access the broker service's gRPC endpoints. Recent minor versions
7 | of both Hadoop 2 & 3 are supported.
8 |
9 | You can find the broker connector's [package on Maven Central](https://search.maven.org/search?q=g:com.google.cloud.broker%20AND%20a:broker-connector):
10 |
11 | ```xml
12 | com.google.cloud.broker
13 | broker-connector
14 | ```
15 |
16 | The broker connector can be downloaded as a single JAR file, which must be placed in the `CLASSPATH` of different
17 | environments:
18 |
19 | - On the user's client node, so the client can access the `GetAccessToken` and `GetSessionToken` endpoints.
20 | - On the master node(s) where the session token renewer (e.g. Yarn) is running, so the renewer can
21 | call the `RenewSessionToken` and `CancelSessionToken` endpoints.
22 | - On the worker nodes, so the distributed tasks can call the `GetAccessToken` to trade a session token for
23 | an access token.
24 |
25 | For more information, see the documentation about [authentication](authentication.md) and [sessions](sessions.md).
26 |
27 | ## Configuration properties
28 |
29 | This section contains all the available Hadoop configuration properties for the broker connector.
30 |
31 | ### `gcp.token.broker.kerberos.principal`
32 |
33 | Full name for the broker's Kerberos service principal.
34 |
35 | ### `gcp.token.broker.uri`
36 |
37 | URI for the broker server. If `https` is specified, then you must also provide either `gcp.token.broker.tls.certificate`
38 | or `gcp.token.broker.tls.certificate.path`.
39 |
40 | ### `gcp.token.broker.tls.certificate`
41 |
42 | Alternative to `gcp.token.broker.tls.certificate.path`. Contents of the TLS certificate for the broker service.
43 | Used only if `gcp.token.broker.tls.enabled` is `true`.
44 |
45 | ### `gcp.token.broker.tls.certificate.path`
46 |
47 | Alternative to `gcp.token.broker.tls.certificate`. File path of TLS certificate for the broker service.
48 | Used only if `gcp.token.broker.tls.enabled` is `true` and `gcp.token.broker.tls.certificate` is not provided.
49 |
50 | ## Configuration checks
51 |
52 | Run this command to verify that your client environment is correctly configured to connect to the server:
53 |
54 | ```shell
55 | java -cp $(hadoop classpath) com.google.cloud.broker.client.hadoop.fs.commands.PingServer
56 | ```
57 |
--------------------------------------------------------------------------------
/docs/concepts/encryption.md:
--------------------------------------------------------------------------------
1 | # Encryption
2 |
3 | The broker encrypts different types of information:
4 |
5 | - Access tokens before they are stored in the [remote cache](caching.md#remote-cache).
6 | - Refresh tokens used by the [refresh token provider](providers.md#refresh-token-provider), if that is the provider
7 | that you elect to use.
8 |
9 | ## Encryption backends
10 |
11 | To select a database backend, set the [`encryption.backend`](settings.md#encryptionbackend) setting
12 | to the backend's class path.
13 |
14 | Below is the list of available database backends:
15 |
16 | ### Cloud KMS
17 |
18 | _Class path:_ `com.google.cloud.broker.encryption.backends.CloudKMSBackend`
19 |
20 | The Cloud KMS backend uses [envelope encryption](https://cloud.google.com/kms/docs/envelope-encryption)
21 | to encrypt and decrypt data. It uses a [Cloud KMS](https://cloud.google.com/kms/) key encryption key (KEK)
22 | to wrap an AES256 data encryption key (DEK) stored in Cloud Storage or on the local filesystem.
23 |
24 | To generate the data encryption key and store it in Cloud Storage, run the
25 | `GenerateDEK` command:
26 |
27 | ```shell
28 | export BROKER_VERSION=$(cat VERSION)
29 | java -cp encryption-backend-cloud-kms-${BROKER_VERSION}-jar-with-dependencies.jar:code/core/target/broker-core-${BROKER_VERSION}-jar-with-dependencies.jar \
30 | com.google.cloud.broker.encryption.GenerateDEK [dekUri] [kekUri]
31 | ```
32 |
33 | * In the above command, replace `[dekUri]` with the URI of the DEK (e.g. `file:///path/to/dek.json` you want to store
34 | the DEK on the local system, or `gs://YOUR_BUCKET/dek.json` if you want to store the DEK on Cloud Storage).
35 | * Replace `[kekUri]` with the URI of the KEK: `projects/[PROJECT]/locations/[REGION]/keyRings/[KEY_RING]/cryptoKeys/[KEY_NAME]`
36 | (Replace the `[PROJECT]`, `[REGION]`, `[KEY_RING]`, and `[KEY_NAME]` with the appropriate values).
37 | * You can omit the `dekUri` and `kekUri` command parameters if you provide a [settings](settings.md) file with the
38 | [`encryption.cloud-kms.dek-uri`](settings.md#encryptioncloud-kmsdek-uri) and
39 | [`encryption.cloud-kms.kek-uri`](settings.md#encryptioncloud-kmskek-uri) settings.
40 |
41 | This backend is available as a [separate package on Maven Central](https://search.maven.org/search?q=g:com.google.cloud.broker%20AND%20a:encryption-backend-cloud-kms):
42 |
43 | ```xml
44 | com.google.cloud.broker
45 | encryption-backend-cloud-kms
46 | ```
47 |
48 | This backend requires that you set the following setting(s): [`encryption.cloud-kms.kek-uri`](settings.md#encryptioncloud-kmskek-uri),
49 | [`encryption.cloud-kms.dek-uri`](settings.md#encryptioncloud-kmsdek-uri).
50 |
51 | ### Dummy encryption backend
52 |
53 | _Class path:_ `com.google.cloud.broker.encryption.backends.DummyEncryptionBackend`
54 |
55 | The Dummy encryption backend doesn't actually encrypt anything. It is only useful for testing
56 | and development purposes. Do _not_ use it in production.
57 |
58 | This backend is included in the [broker server](broker-server.md) package.
59 |
--------------------------------------------------------------------------------
/docs/concepts/index.md:
--------------------------------------------------------------------------------
1 | # Concepts
2 |
3 | The conceptual documentation is divided in the following topics (here listed in alphabetical order):
4 |
5 | - [Access token providers](providers.md): All the different ways that the broker can generate access tokens.
6 | - [Authentication](authentication.md): All the different methods that clients can use to authenticate with the broker service.
7 | - [Authorizer](authorizer.md): How to use the Authorizer app.
8 | - [Broker connector](connector.md): How to use the broker connector, the client library to access the broker service from Hadoop.
9 | - [Broker server](broker-server.md): How to run the broker server app.
10 | - [Caching](caching.md): How the broker caches information for performance.
11 | - [Database](database.md): How the broker stores state.
12 | - [Encryption](encryption.md): How the broker encrypts sensitive information.
13 | - [Logging](logging.md): How to enable and view audit logs.
14 | - [Sessions](sessions.md): All you need to know about broker sessions.
15 | - [Settings](settings.md): List of all available settings.
16 | - [TLS](tls.md): Securing transport between broker clients and the broker service with TLS.
17 | - [User mapping](user-mapping.md): Mapping third-party user names to Google identity names.
18 |
--------------------------------------------------------------------------------
/docs/concepts/logging.md:
--------------------------------------------------------------------------------
1 | # Logging
2 |
3 | ## Enabling GCS audit logs
4 |
5 | Follow these steps to enable GCS audit logs:
6 |
7 | 1. Go to:
8 |
9 | 2. In the "Filter table" text box, type "Google Cloud Storage" then press the "Enter" key.
10 |
11 | 3. Click on the "Google Cloud Storage" entry.
12 |
13 | 4. Tick the 3 checkboxes: "Admin Read", "Data Read", "Data Write".
14 |
15 | 5. Click "Save".
16 |
17 | ## Viewing GCS audit logs
18 |
19 | Follow these steps to view the GCS audit logs in Stackdriver:
20 |
21 | 1. Open the logs viewer in Stackdriver:
22 |
23 | 2. Click the down arrow in the text search box, then click "Convert to advanced filter".
24 |
25 | 3. Type the following in the text search box (Replace the **two** **`[PROJECT-ID]`** instances
26 | with your project ID and **`[BUCKET-NAME]`** with the name of your bucket):
27 |
28 | ```conf
29 | resource.type="gcs_bucket"
30 | resource.labels.bucket_name="[BUCKET-NAME]"
31 | logName="projects/[PROJECT-ID]/logs/cloudaudit.googleapis.com%2Fdata_access"
32 | ```
33 |
34 | 4. Click "Submit Filter".
35 |
--------------------------------------------------------------------------------
/docs/concepts/tls.md:
--------------------------------------------------------------------------------
1 | # TLS
2 |
3 | Communication between the [broker connector](connector.md) and the [broker server](broker-server.md) can be
4 | encrypted with [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security).
5 |
6 | TLS encryption is **highly recommended** for production environments.
7 |
8 | To enable TLS:
9 |
10 | 1. Create a domain for the broker service.
11 | 2. Get a certificate and private key from a [certificate authority](https://en.wikipedia.org/wiki/Certificate_authority).
12 | 3. Set the [`server.tls.enabled`](settings.md#servertlsenabled) setting to `true` and provide the certificate and
13 | private key with the [`server.tls.certificate-path`](settings.md#servertlscertificate-path) and
14 | [`server.tls.private-key-path`](settings.md#servertlsprivate-key-path) setting.
15 | 4. Configure the broker connector's [properties](connector.md#configuration-properties) to use TLS.
16 |
--------------------------------------------------------------------------------
/docs/contribute/development.md:
--------------------------------------------------------------------------------
1 | ## Development
2 |
3 | ### Creating a development container
4 |
5 | You can use docker to create a container dedicated for development tasks.
6 |
7 | Create the container by running this command **from the repository's root**:
8 |
9 | ```shell
10 | ./run.sh init_dev
11 | ```
12 |
13 | This installs all the dependencies needed to build packages and run the tests.
14 |
15 | ### Building packages
16 |
17 | To build all packages:
18 |
19 | ```shell
20 | ./run.sh build
21 | ```
22 |
23 | To build an extension, for example the Redis caching backend:
24 |
25 | ```shell
26 | ./run.sh build -m redis
27 | ```
28 |
29 | To build the broker connector:
30 |
31 | ```shell
32 | ./run.sh build -m connector
33 | ```
34 |
35 | ### Building containers
36 |
37 | ```shell
38 | # Broker service
39 | docker build -f ./code/broker-server/Dockerfile -t gcr.io/${PROJECT}/broker-server .
40 | docker push gcr.io/$PROJECT/broker-server
41 |
42 | # Authorizer
43 | docker build -f ./code/authorizer/Dockerfile -t gcr.io/${PROJECT}/authorizer .
44 | docker push gcr.io/$PROJECT/authorizer
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/contribute/index.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Getting started
7 |
8 | Check out the following links to get started if you're interested in making code contributions
9 | to this project:
10 |
11 | - Set up a [development](development.md) environment
12 | - Run the [regression tests](regression-tests.md)
13 | - Run the [load tests](load-tests.md)
14 |
15 | Every contribution for bug fixes and new features should include unit tests and documentation to
16 | benefit other developers and facilitate the long-term maintenance of this project.
17 |
18 | Whenever possible, keep each pull request focused on a specific code change. Avoid mixing multiple
19 | bug fixes or new features in the same pull request. This will make it easier for the project
20 | maintainers to review your individual pull requests. This will also allow merging the reviewed
21 | PRs faster and not block them if other code changes need extra review time.
22 |
23 | Also, it is preferable to create pull requests based on the official master branch.
24 |
25 | ## Contributor License Agreement
26 |
27 | Contributions to this project must be accompanied by a Contributor License
28 | Agreement. You (or your employer) retain the copyright to your contribution;
29 | this simply gives us permission to use and redistribute your contributions as
30 | part of the project. Head over to to see
31 | your current agreements on file or to sign a new one.
32 |
33 | You generally only need to submit a CLA once, so if you've already submitted one
34 | (even if it was for a different project), you probably don't need to do it
35 | again.
36 |
37 | ## Code reviews
38 |
39 | All submissions, including submissions by project members, require review. We
40 | use GitHub pull requests for this purpose. Consult
41 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
42 | information on using pull requests.
43 |
44 | ## Community Guidelines
45 |
46 | This project follows
47 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
48 |
--------------------------------------------------------------------------------
/docs/contribute/load-tests.md:
--------------------------------------------------------------------------------
1 | ## Load testing
2 |
3 | This repository contains some load tests that use the [Locust](https://locust.io/) framework.
4 |
5 | You can run the load tests from the sample Dataproc cluster that you created for the demo.
6 |
7 | 1. SSH into the Dataproc master instance:
8 |
9 | ```shell
10 | gcloud compute ssh test-cluster-m
11 | ```
12 |
13 | 2. Clone the project's repository:
14 |
15 | ```shell
16 | git clone https://github.com/GoogleCloudPlatform/gcp-token-broker
17 | cd gcp-token-broker/load-testing
18 | ```
19 |
20 | 3. Install some dependencies:
21 |
22 | ```shell
23 | ./install.sh
24 | ```
25 |
26 | 4. Create the Python gRPC stubs:
27 |
28 | ``shell
29 | python3 -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. brokerservice/protobuf/broker.proto
30 | ```
31 |
32 | 5. Create a `settings.py` file using the provided template.
33 |
34 | ```shell
35 | cp settings.py.template settings.py
36 | ```
37 |
38 | 6. Edit the `settings.py` to set appropriate values for your setup.
39 |
40 | 7. To run the load tests in headless mode:
41 |
42 | ```shell
43 | ~/.local/bin/locust --no-web -c 1000 -r 10
44 | ```
45 | The `-c` corresponds to the total number of users, and `-r` the hatch rate
46 | (i.e. the number of new users spawned each passing second). To stop the tests,
47 | press `ctrl-c`.
48 |
49 | 8. To run the tests using the Web UI, start the Locust server:
50 |
51 | ```shell
52 | ~/.local/bin/locust
53 | ```
54 | Then, in another terminal on your local machine, run the following command to set up
55 | a tunnel with the Dataproc master instance:
56 |
57 | ```shell
58 | gcloud compute start-iap-tunnel test-cluster-m 8089 \
59 | --local-host-port=localhost:8089
60 | --zone $ZONE
61 | ```
62 | Then open your browser at the address `http://localhost:8089`
63 |
64 | Note: During the execution of load tests, you might see some errors: `Too many open files`.
65 | This is because all users must read the Kerberos credentials from a temporary cache file,
66 | and the limit of open files allowed by the OS might be reached. To increase the limit, run
67 | the following command:
68 |
69 | ```shell
70 | ulimit -n 32768
71 | ```
72 |
--------------------------------------------------------------------------------
/docs/img/delegated-auth-sequence.txt:
--------------------------------------------------------------------------------
1 | participant alice\n@YOUR.REALM.COM as Alice
2 | participant Hadoop\nClient as Client
3 | participant GCS Connector\n(in Hadoop Client) as GCSConnClient
4 | participant On prem\nKDC as OnPremKDC
5 | participant Broker as Broker
6 | participant Yarn\nresource\nmanager as Yarn
7 | participant Client\nKDC as ClientKDC
8 | participant Yarn task as Task
9 | participant GCS Connector\n(in Task) as GCSConnTask
10 | participant GCS
11 |
12 | Alice -> Client: Submit job
13 | Client -> GCSConnClient: Read objects
14 | GCSConnClient -> OnPremKDC: Get SPNEGO token
15 | OnPremKDC -> GCSConnClient: Return SPNEGO token
16 | GCSConnClient -> Broker: Get session token\n(SPNEGO token) [fillcolor="white"]
17 | Broker -> Broker: Authenticate\nalice@YOUR.REALM.COM\nwith Kerberos/SPNEGO
18 | Broker -> Broker: Generate new\nsession token
19 | Broker -> Broker: Store session\ntoken details in\nbroker database
20 | Broker -> GCSConnClient: Return session token[fillcolor="white"]
21 | GCSConnClient -> Client: Return\nsession\ntoken
22 | Client -> Client: Store\nsession\ntoken in\njob context\nand UGI
23 | Client -> Yarn: Submit job [fillcolor="white"]
24 | Yarn -> ClientKDC: Get SPNEGO token
25 | ClientKDC -> Yarn: Return SPNEGO token
26 | Yarn -> Broker: Renew session token\n(SPNEGO token)
27 | Broker -> Broker: Authenticate Yarn\nwith Kerberos/SPNEGO
28 | Broker -> Broker: Verify Yarn is\nauthorized renewer
29 | Broker -> Broker: Extend session\ntoken's lifetime
30 | Yarn -> Task: Submit job[fillcolor="white"]
31 | Task -> GCSConnTask: Read\nobjects
32 | GCSConnTask -> GCSConnTask: Retrieve\nsession\ntoken from\nthe UGI[fillcolor="white"]
33 | GCSConnTask -> Broker: Get access token (session token)[fillcolor="white"]
34 | Broker -> Broker: Generate new\naccess token for\nalice@your-domain.com
35 | Broker -> GCSConnTask: Return access token[fillcolor="white"]
36 | GCSConnTask -> GCS: Read\nobjects
37 | GCS -> GCS: Verify\naccess\ncontrol\nfor alice\n@your-domain.com
38 | GCS -> GCSConnTask: Return\nobjects
39 | GCSConnTask -> Task: Return\nobjects
40 | Task -> Task: Process\nobjects
41 | Note over Task: Job runs until\ncompletion...[fillcolor="white"]
42 | Yarn -> Client: Return job result [fillcolor="white"]
43 | Yarn -> ClientKDC: Get SPNEGO token
44 | ClientKDC -> Yarn: Return SPNEGO token
45 | Yarn -> Broker: Cancel\nsession token\n(SPNEGO token)
46 | Broker -> Broker: Authenticate Yarn\nwith Kerberos/SPNEGO
47 | Broker -> Broker: Verify Yarn is\nauthorized renewer
48 | Broker -> Broker: Delete\nsession token\nfrom database
--------------------------------------------------------------------------------
/docs/img/direct-auth-sequence.txt:
--------------------------------------------------------------------------------
1 | participant alice\n@YOUR.REALM.COM as Alice
2 | participant Hadoop Client as Client
3 | participant GCS Connector as GCSConn
4 | participant On prem\nKDC as OnPremKDC
5 | participant Broker as Broker
6 | participant GCS
7 |
8 | Alice -> Client: Submit job
9 | Client -> GCSConn: Read objects
10 | GCSConn -> OnPremKDC: Get SPNEGO token
11 | OnPremKDC -> GCSConn: Return SPNEGO token
12 | GCSConn -> Broker: Get access token\n(SPNEGO token) [fillcolor="white"]
13 | Broker -> Broker: Authenticate\nalice@YOUR.REALM.COM\nwith Kerberos/SPNEGO
14 | Broker -> Broker: Generate new\naccess token for\nalice@your-domain.com
15 | Broker -> GCSConn: Return access token [fillcolor="white"]
16 | GCSConn -> GCS: Read objects (access token)[fillcolor="white"]
17 | GCS -> GCS: Verify access\ncontrol for\nalice@your-domain.com
18 | GCS -> GCSConn: Return objects [fillcolor="white"]
19 | GCSConn -> Client: Return objects
--------------------------------------------------------------------------------
/docs/img/dwd-admin-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/gcp-token-broker/2f70368c138d263b022a892f5442cc4b92b2d5fa/docs/img/dwd-admin-screen.png
--------------------------------------------------------------------------------
/docs/img/dwd-service-accounts-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/gcp-token-broker/2f70368c138d263b022a892f5442cc4b92b2d5fa/docs/img/dwd-service-accounts-screen.png
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ## Documentation
2 |
3 | The documentation is organized in different sections:
4 |
5 | - [Conceptual guides](concepts/index.md) discuss key concepts at a high-level and provide explanation
6 | about the design and rationale for the broker's components and behavior.
7 | - [Deployment guides](deploy/index.md) take you through a series of steps to deploy the broker service on GCP.
8 | - [Tutorials](tutorials/index.md) show some examples for testing the broker's functionality.
9 | - The [contributing guide](contribute/index.md) provides tips to get you started if you'd like to contribute code
10 | to this project.
11 |
--------------------------------------------------------------------------------
/kubernetes/broker-server/templates/session-cleanup.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: batch/v1beta1
13 | kind: CronJob
14 | metadata:
15 | name: {{ .Chart.Name }}-session-cleanup
16 | labels:
17 | app: {{ .Chart.Name }}
18 | chart: '{{ .Chart.Name }}-{{ .Chart.Version }}'
19 | release: '{{ .Release.Name }}'
20 | heritage: '{{ .Release.Service }}'
21 | spec:
22 | schedule: '{{ .Values.sessionCleanup.schedule }}'
23 | jobTemplate:
24 | spec:
25 | template:
26 | spec:
27 | containers:
28 | - name: {{ .Chart.Name }}-session-cleanup-container
29 | image: {{ .Values.broker.image }}
30 | env:
31 | - name: CONFIG_FILE
32 | value: "/config/application.conf"
33 | command:
34 | - java
35 | - -cp
36 | - /classpath/*
37 | - com.google.cloud.broker.apps.brokerserver.sessions.SessionCleanup
38 | volumeMounts:
39 | - name: {{ .Chart.Name }}-config-volume
40 | mountPath: '/config'
41 | restartPolicy: OnFailure
42 | volumes:
43 | - name: {{ .Chart.Name }}-config-volume
44 | configMap:
45 | name: {{ .Chart.Name }}-settings-configmap
--------------------------------------------------------------------------------
/load-testing/brokerservice/protobuf/broker.proto:
--------------------------------------------------------------------------------
1 | ../../../code/broker-server/src/main/proto/broker.proto
--------------------------------------------------------------------------------
/load-testing/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Google LLC
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | sudo apt-get install -y python3
15 | sudo apt-get install -y libkrb5-dev
16 | python3 -m pip install --user locustio==0.11.0 grpcio==1.19.0 grpcio-tools==1.19.0 gssapi==1.5.1 protobuf==3.6.1
--------------------------------------------------------------------------------
/load-testing/locustfile.py:
--------------------------------------------------------------------------------
1 | # Copyright Google Inc. 2019
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | import subprocess
13 |
14 | from locust import Locust, TaskSequence, task, seq_task
15 |
16 | from client import BrokerClient
17 | from settings import TEST_USERS, REALM
18 |
19 | SCOPE = 'https://www.googleapis.com/auth/devstorage.read_write'
20 | BROKER_HOST = '10.2.1.255.nip.io'
21 | USER = TEST_USERS[0]
22 | USER_FULL = '{}@{}'.format(USER, REALM)
23 |
24 |
25 | def get_certificate():
26 | # Retrieve the TLS certificate from the VM metadata
27 | out = subprocess.Popen(
28 | ['/usr/share/google/get_metadata_value', 'attributes/gcp-token-broker-tls-certificate'],
29 | stdout=subprocess.PIPE,
30 | stderr=subprocess.STDOUT)
31 | certificate, _ = out.communicate()
32 | return certificate
33 |
34 |
35 | class JobSimulation(TaskSequence):
36 |
37 | def on_start(self):
38 | self.client.kinit(USER_FULL, USER)
39 |
40 | def on_stop(self):
41 | self.client.kdestroy()
42 |
43 | @seq_task(1)
44 | def get_session_token(self):
45 | response = self.client.call_endpoint(
46 | 'GetSessionToken',
47 | parameters=dict(owner=USER_FULL, scopes=[SCOPE], renewer=USER_FULL)
48 | )
49 | self.session_token = response.session_token
50 |
51 | @seq_task(2)
52 | def renew_session_token(self):
53 | self.client.call_endpoint(
54 | 'RenewSessionToken',
55 | parameters=dict(session_token=self.session_token),
56 | )
57 |
58 | @seq_task(3)
59 | @task(100)
60 | def get_access_token(self):
61 | self.client.call_endpoint(
62 | 'GetAccessToken',
63 | session_token=self.session_token
64 | )
65 |
66 | @seq_task(4)
67 | def cancel_session_token(self):
68 | self.client.call_endpoint(
69 | 'CancelSessionToken',
70 | parameters=dict(session_token=self.session_token),
71 | )
72 |
73 |
74 | class BrokerUser(Locust):
75 | host = BROKER_HOST
76 | task_set = JobSimulation
77 | min_wait = 0
78 | max_wait = 1
79 |
80 | def __init__(self, *args, **kwargs):
81 | self.client = BrokerClient(self.host, get_certificate())
82 |
--------------------------------------------------------------------------------
/load-testing/settings.py.template:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | REALM = ''
13 | TEST_USERS = ['alice', 'bob', 'john']
--------------------------------------------------------------------------------
/terraform/peering.tf:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 |
13 | // Client <--> Origin ---------------------------------------------------------------
14 |
15 | resource "google_compute_network_peering" "client_origin_peering1" {
16 | name = "client-origin-peering1"
17 | network = google_compute_network.client.self_link
18 | peer_network = google_compute_network.origin.self_link
19 | depends_on = [
20 | google_compute_subnetwork.origin_subnet,
21 | google_compute_subnetwork.client_subnet,
22 | ]
23 | }
24 |
25 | resource "google_compute_network_peering" "client_origin_peering2" {
26 | name = "client-origin-peering2"
27 | network = google_compute_network.origin.self_link
28 | peer_network = google_compute_network.client.self_link
29 | }
30 |
--------------------------------------------------------------------------------
/terraform/shadow.tf:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | resource "google_service_account" "test_user_serviceaccount" {
13 | count = length(var.test_users)
14 | account_id = "${element(var.test_users, count.index)}-shadow"
15 | display_name = "${element(var.test_users, count.index)}'s shadow service account"
16 | }
17 |
18 | resource "google_service_account_iam_member" "token_creator_0" {
19 | service_account_id = google_service_account.test_user_serviceaccount[0].name
20 | role = "roles/iam.serviceAccountTokenCreator"
21 | member = "serviceAccount:${google_service_account.broker.email}"
22 | }
23 |
24 | resource "google_service_account_iam_member" "token_creator_1" {
25 | service_account_id = google_service_account.test_user_serviceaccount[1].name
26 | role = "roles/iam.serviceAccountTokenCreator"
27 | member = "serviceAccount:${google_service_account.broker.email}"
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/terraform/startup-script-kdc.tpl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | # In general we want to enable debug through -x
13 | # But there are also some commands involving passwords/keys
14 | # so make sure you turn it off (set +x) before such commands.
15 | set -xeuo pipefail
16 |
17 | apt-get update
18 |
19 | DEBIAN_FRONTEND=noninteractive apt-get -yq install krb5-kdc krb5-admin-server
20 |
21 | cat << EOF > /etc/krb5.conf
22 | [realms]
23 | ${realm} = {
24 | kdc = localhost:88
25 | admin_server = localhost:749
26 | }
27 | [libdefaults]
28 | default_realm = ${realm}
29 | dns_lookup_realm = false
30 | dns_lookup_kdc = false
31 | EOF
32 |
33 |
34 | cat << EOF > /etc/krb5kdc/kdc.conf
35 | [kdcdefaults]
36 | kdc_ports = 750,88
37 |
38 | [realms]
39 | ${realm} = {
40 | database_name = /var/lib/krb5kdc/principal
41 | admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
42 | acl_file = /etc/krb5kdc/kadm5.acl
43 | key_stash_file = /etc/krb5kdc/stash
44 | kdc_ports = 750,88
45 | max_life = 10h 0m 0s
46 | max_renewable_life = 7d 0h 0m 0s
47 | master_key_type = aes256-cts
48 | supported_enctypes = aes256-cts:normal arcfour-hmac:normal des3-hmac-sha1:normal des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3
49 | default_principal_flags = +preauth
50 | }
51 | EOF
52 |
53 |
54 | cat << EOF >> /etc/krb5kdc/kadm5.acl
55 | root *
56 | EOF
57 |
58 | mkdir /var/log/kerberos
59 | touch /var/log/kerberos/krb5libs.log
60 | touch /var/log/kerberos/krb5kdc.log
61 | touch /var/log/kerberos/kadmind.log
62 |
63 | KDC_DB_KEY=$(openssl rand -base64 32)
64 | /usr/sbin/kdb5_util create -s -W -P "$${KDC_DB_KEY}"
65 |
66 | systemctl enable krb5-kdc; systemctl restart krb5-kdc
67 | systemctl enable krb5-admin-server; systemctl restart krb5-admin-server
68 |
69 | kadmin.local -q "addprinc -randkey root"
70 |
71 | ${extra_commands}
72 |
73 | echo "
74 | export REALM=${realm}
75 | export PROJECT=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
76 | export ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/zone" -H "Metadata-Flavor: Google" | awk -F/ '{print $NF}')
77 | " > /etc/profile.d/extra_env_vars.sh
--------------------------------------------------------------------------------
/terraform/variables.tf:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | variable "gcp_project" {
13 | }
14 |
15 | variable "gcp_region" {
16 | default = "us-west1"
17 | }
18 |
19 | variable "gcp_zone" {
20 | default = "us-west1-a"
21 | }
22 |
23 | variable "datastore_region" {
24 | default = "us-west2"
25 | }
26 |
27 | variable "origin_realm" {
28 | }
29 |
30 | variable "gsuite_domain" {
31 | }
32 |
33 | // Origin KDC --------------------------------------
34 |
35 | variable "origin_subnet_cidr" {
36 | default = "10.11.0.0/29"
37 | }
38 |
39 | variable "origin_kdc_ip" {
40 | default = "10.11.0.3"
41 | }
42 |
43 | // Client ----------------------------------------
44 |
45 | variable "client_subnet_cidr" {
46 | default = "10.21.0.0/16"
47 | }
48 |
49 | variable "dataproc_root_password" {
50 | default = "change-me"
51 | }
52 |
53 | // Cross-realm trust -----------------------------
54 |
55 | variable "cross_realm_password" {
56 | default = "change-me"
57 | }
58 |
59 | variable dataproc_realm {
60 | default = "DATAPROC_REALM"
61 | }
62 |
63 | // Test users ------------------------------------
64 |
65 | variable "test_users" {
66 | type = list(string)
67 | default = ["alice", "bob", "charlie"]
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/terraform/versions.tf:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | terraform {
13 | required_version = ">= 0.12"
14 | }
15 |
16 | terraform {
17 | required_providers {
18 | google = {
19 | source = "hashicorp/google"
20 | version = "4.31.0"
21 | }
22 | null = {
23 | source = "hashicorp/null"
24 | version = "3.1.1"
25 | }
26 | template = {
27 | source = "hashicorp/template"
28 | version = "2.2.0"
29 | }
30 | local = {
31 | source = "hashicorp/local"
32 | version = "2.2.3"
33 | }
34 | }
35 | }
36 |
37 | provider "google" {
38 | project = var.gcp_project
39 | region = var.gcp_region
40 | zone = var.gcp_zone
41 | }
--------------------------------------------------------------------------------