Skip to content

Commit

Permalink
chore: add credential factory classes and tests (#295)
Browse files Browse the repository at this point in the history
  • Loading branch information
ttosta-google committed Nov 10, 2023
1 parent 5b1bfba commit f84cea0
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;

class ConstantCredentialFactory implements CredentialFactory {

private final GoogleCredentials credentials;

public ConstantCredentialFactory(GoogleCredentials credentials) {
this.credentials = credentials;
}

@Override
public FixedCredentialsProvider create() {
return FixedCredentialsProvider.create(getCredentials());
}

@Override
public GoogleCredentials getCredentials() {
return credentials;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;

interface CredentialFactory {
default FixedCredentialsProvider create() {
return FixedCredentialsProvider.create(getCredentials());
}

GoogleCredentials getCredentials();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;

class DefaultCredentialFactory implements CredentialFactory {
@Override
public GoogleCredentials getCredentials() {
try {
return GoogleCredentials.getApplicationDefault();
} catch (IOException e) {
throw new RuntimeException("failed to retrieve OAuth2 access token", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import com.google.auth.oauth2.GoogleCredentials;
import java.io.FileInputStream;
import java.io.IOException;

class FileCredentialFactory implements CredentialFactory {
private final String path;

FileCredentialFactory(String path) {
this.path = path;
}

@Override
public GoogleCredentials getCredentials() {
try {
return GoogleCredentials.fromStream(new FileInputStream(path));
} catch (IOException e) {
throw new IllegalStateException("Unable to load GoogleCredentials from file " + path, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ImpersonatedCredentials;
import java.util.Arrays;
import java.util.List;

/**
* Wraps an existing CredentialFactory to impersonate the targetPrincipal, with an optional list of
* delegating service accounts in accordance with the ImpersonatedCredentials API.
*
* <p>targetPrincipal – the service account to impersonate
*
* <p>delegates – the chained list of delegates required to grant the final access_token. If set,
* the sequence of identities must have "Service Account Token Creator" capability granted to the
* preceding identity. For example, if set to [serviceAccountB, serviceAccountC], the
* sourceCredential must have the Token Creator role on serviceAccountB. serviceAccountB must have
* the Token Creator on serviceAccountC. Finally, C must have Token Creator on target_principal. If
* unset, sourceCredential must have that role on targetPrincipal.
*
* @see com.google.auth.oauth2.ImpersonatedCredentials
*/
class ServiceAccountImpersonatingCredentialFactory implements CredentialFactory {

private static final String CLOUD_PLATFORM = "https://www.googleapis.com/auth/cloud-platform";
private static final String ALLOYDB_LOGIN = "https://www.googleapis.com/auth/alloydb.login";
private final CredentialFactory source;
private final List<String> delegates;
private final String targetPrincipal;

/**
* Creates a new ServiceAccountImpersonatingCredentialFactory.
*
* @param source the source of the original credentials, before they are impersonated.
* @param targetPrincipal The target principal in the form of a service account, must not be null.
* @param delegates The optional list of delegate service accounts, may be null or empty.
*/
ServiceAccountImpersonatingCredentialFactory(
CredentialFactory source, String targetPrincipal, List<String> delegates) {
if (targetPrincipal == null || targetPrincipal.isEmpty()) {
throw new IllegalArgumentException("targetPrincipal must not be empty");
}
this.source = source;
this.delegates = delegates;
this.targetPrincipal = targetPrincipal;
}

@Override
public GoogleCredentials getCredentials() {
GoogleCredentials credentials = source.getCredentials();

credentials =
ImpersonatedCredentials.newBuilder()
.setSourceCredentials(credentials)
.setTargetPrincipal(targetPrincipal)
.setDelegates(this.delegates)
.setScopes(Arrays.asList(ALLOYDB_LOGIN, CLOUD_PLATFORM))
.build();
return credentials;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import com.google.auth.oauth2.GoogleCredentials;
import java.util.function.Supplier;

class SupplierCredentialFactory implements CredentialFactory {

private final Supplier<GoogleCredentials> supplier;

public SupplierCredentialFactory(Supplier<GoogleCredentials> supplier) {
this.supplier = supplier;
}

@Override
public GoogleCredentials getCredentials() {
return supplier.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import static com.google.common.truth.Truth.assertThat;

import com.google.auth.oauth2.GoogleCredentials;
import org.junit.Test;

public class ConstantCredentialsFactoryTest {

@Test
public void testConstantCredentials() {
GoogleCredentials c = GoogleCredentials.create(null);
ConstantCredentialFactory f = new ConstantCredentialFactory(c);
assertThat(f.getCredentials()).isSameInstanceAs(c);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.*;

import com.google.auth.oauth2.GoogleCredentials;
import org.junit.Test;

public class FileCredentialFactoryTest {

@Test
public void getCredentials_failsWhenNoFileExists() {
FileCredentialFactory f = new FileCredentialFactory("nope");
assertThrows(IllegalStateException.class, f::getCredentials);
}

@Test
public void getCredentials_loadsFromFilePath() {
String path = FileCredentialFactoryTest.class.getResource("/sample-credentials.json").getFile();
FileCredentialFactory f = new FileCredentialFactory(path);
GoogleCredentials c = f.getCredentials();
assertThat(c.getQuotaProjectId()).isEqualTo("sample");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.alloydb;

import static com.google.common.truth.Truth.assertThat;

import com.google.auth.oauth2.GoogleCredentials;
import org.junit.Test;

public class SupplierCredentialFactoryTest {

@Test
public void getCredentials() {
GoogleCredentials c = GoogleCredentials.create(null);
SupplierCredentialFactory f = new SupplierCredentialFactory(() -> c);
assertThat(f.getCredentials()).isSameInstanceAs(c);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"client_id": "sample.apps.googleusercontent.com",
"client_secret": "sample",
"quota_project_id": "sample",
"refresh_token": "sample",
"access_token": "sample",
"type": "authorized_user"
}

0 comments on commit f84cea0

Please sign in to comment.