Skip to content

Conversation

@JesseLovelace
Copy link
Contributor

Fixes #5054

Adds support for HMAC service accounts. Holding off on adding documentation until the general implementation is approved

@JesseLovelace JesseLovelace requested a review from jkwlui June 3, 2019 20:21
@JesseLovelace JesseLovelace requested a review from a team as a code owner June 3, 2019 20:21
@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Jun 3, 2019
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Jun 10, 2019
@JesseLovelace JesseLovelace requested a review from frankyn June 13, 2019 21:14
}

public static class Builder {
private String secretKey;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super familiar with documenting Java code, but can we add a note saying the secret is only available on creation?

Copy link
Contributor Author

@JesseLovelace JesseLovelace Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah--I'm planning to add the documentation once the code is otherwise approved

Copy link
Member

@jkwlui jkwlui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surface looks good! Thanks Jesse. Please hold off from merging until we're ready to release.


@Override
public int hashCode() {
return Objects.hash(secretKey, metadata);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space here?

Copy link
Contributor

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @JesseLovelace, I've added some minor comments.

Could you also run the code through the Google Java linter?

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.BaseEncoding;
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, would need "HmacKey.HmacKeyMetadata" without it

*/
List<ObjectAccessControl> listAcls(String bucket, String object, Long generation);

HmacKey createHmacKey(String serviceAccountEmail);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Test
public void testHmacKey() {
ServiceAccount serviceAccount =
ServiceAccount.of("[email protected]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an environment variable value.

import com.google.common.io.BaseEncoding;
import com.google.common.net.UrlEscapers;
import com.google.common.primitives.Ints;
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, would need "HmacKey.HmacKeyMetadata" without it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, gotcha. Thanks for clarifying!


void deleteHmacKey(String accessId);

HmacKeyMetadata updateHmacKeyState(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice helper method! (no action required).

ServiceAccount serviceAccount, String pageToken, Long maxResults, boolean showDeletedKeys);

/**
* Lists HMAC keys for a given service account. Note this returns {@code HmacKeyMetadata} objects,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lists active HMAC keys for a given service account.

* <pre>{@code
* ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
*
* Page<HmacKey.HmacKeyMetadata> metadataPage = storage.listHmacKeys(serviceAccount, null, 10);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add the boolean value of true for Deleted keys?

*/
Page<HmacKeyMetadata> listHmacKeys(
ServiceAccount serviceAccount, String pageToken, Long maxResults);
ServiceAccount serviceAccount, String pageToken, Long maxResults, boolean showDeletedKeys);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why the overload for showDeletedKeys?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reasoning here is that the most common use case is going to be listHmacKeys(serviceAccount), so offering that along with one other signature to be more precise would meet most needs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha that makes sense. What about defaulting to not showing deleted keys?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is already the default I believe

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API defaults to false if not given.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jkwlui and @JesseLovelace!

@codecov
Copy link

codecov bot commented Jun 21, 2019

Codecov Report

Merging #5284 into master will decrease coverage by 3.09%.
The diff coverage is 6.45%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #5284      +/-   ##
============================================
- Coverage     50.48%   47.38%    -3.1%     
- Complexity    23890    27180    +3290     
============================================
  Files          2258     2523     +265     
  Lines        227482   274574   +47092     
  Branches      24973    31380    +6407     
============================================
+ Hits         114834   130112   +15278     
- Misses       104029   134852   +30823     
- Partials       8619     9610     +991
Impacted Files Coverage Δ Complexity Δ
...ain/java/com/google/cloud/storage/StorageImpl.java 77.81% <0%> (-8.39%) 98 <0> (-5)
...om/google/cloud/storage/spi/v1/HttpStorageRpc.java 1.64% <0%> (-0.19%) 1 <0> (ø)
...rc/main/java/com/google/cloud/storage/Storage.java 79.72% <0%> (-6.13%) 0 <0> (ø)
...ogle/cloud/storage/spi/v1/HttpStorageRpcSpans.java 100% <100%> (ø) 3 <0> (ø) ⬇️
...va/com/google/cloud/storage/spi/v1/StorageRpc.java 64.38% <100%> (+1.52%) 0 <0> (ø) ⬇️
...ud/storage/contrib/nio/testing/FakeStorageRpc.java 59.66% <40%> (-4.07%) 44 <0> (+3)
...rc/main/java/com/google/cloud/storage/HmacKey.java 5.73% <5.73%> (ø) 0 <0> (?)
...n/java/com/google/cloud/bigquery/BigQueryImpl.java 66.78% <0%> (-13.22%) 57% <0%> (ø)
...a/com/google/cloud/firestore/FirestoreOptions.java 36.97% <0%> (-7.82%) 7% <0%> (ø)
... and 938 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e4f56e8...61187df. Read the comment docs.

@frankyn frankyn requested a review from jkwlui June 21, 2019 21:46
*
* @throws StorageException upon failure
*/
Page<HmacKeyMetadata> listHmacKeys(ServiceAccount serviceAccount);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

listHmacKeys should also be able to accept no serviceAccount, which will show HMAC keys from all accounts. Can your implementation accept no serviceAccount?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Listing keys from all accounts can be accomplished by calling this with serviceAccount=null. I'll add a note about it in the documentation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. That would really help, thank you!

@JesseLovelace JesseLovelace added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jun 26, 2019
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jun 26, 2019
@yoshi-automation yoshi-automation removed the 🚨 This issue needs some love. label Jul 3, 2019
Copy link
Contributor

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding an additional request for consistency with the Storage surface and HMACKey RPCs.

* @throws StorageException upon failure
*/
Page<HmacKeyMetadata> listHmacKeys(
ServiceAccount serviceAccount, String pageToken, Long maxResults, boolean showDeletedKeys);
Copy link
Contributor

@frankyn frankyn Jul 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on other RPCs the Storage library has, the following parameters: serviceAccountEmail, pageToken, showDeletedKeys, and maxResults should be listed under an Options optional parameter because they are optional. The only required value is project_id which is provided by client credentials.

Other HmacKey RPCs should have a similar Options parameter for the value userProject. At the moment it's ignored by the service but it's expected to be available. Given it would change the signature of the method I thought it'd be best to do it now rather than wait until later. (I'm open to opinions here).

Copy link
Contributor

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last nit which is to expose userProject in each new RPC method.

* Returns an option to specify whether to show deleted keys in the result. This option is false
* by default.
*/
public static ListHmacKeysOption showDeletedKeys(boolean showDeletedKeys) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userProject should be available based on the discovery document. https://www.googleapis.com/discovery/v1/apis/storage/v1/rest

*
* @throws StorageException upon failure
*/
HmacKey createHmacKey(ServiceAccount serviceAccount);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include options for userProject.

*
* @throws StorageException upon failure
*/
HmacKeyMetadata getHmacKey(String accessId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include options for userProject.

*
* @throws StorageException upon failure
*/
void deleteHmacKey(String accessId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include options for userProject.

* @throws StorageException upon failure
*/
HmacKeyMetadata updateHmacKeyState(
final HmacKeyMetadata hmacKeyMetadata, final HmacKey.HmacKeyState state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include options for userProject.

Copy link
Contributor

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few last nits. Thank you for your patience.

*
* @throws StorageException upon failure
*/
void deleteHmacKey(String accessId, DeleteHmacKeyOption... options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to interpretation on the following. PLMK what you think.
There should use HMACKeyMetadata as a parameter instead of String accessId. This may not happen often so I'm thinking we should not have this overload (provided examples below). The HMACKeyMetadata can then provide the projectId as well. We don't need HmacKeyOption.PROJECT_ID option in this case.

I would expect this to be a common case given the current surface:

// Delete an hmac key.
String hmacKeyAccessId = "my-access-id";

HmacKey.HmackeyMetadata hmacKeyMetadata = storage.getHmacKey(hmacKeyAccessId);

hmacKeyMetadata = storage.updateHmacKeyState(hmacKeyMetadata, HmacKey.HmacKeyState.INACTIVE);

storage.deleteHmacKey(hmacKeyMetadata);

Here's an example that expects the key to be deactivated. A user needs a deactivated key.

// Delete an hmac key has the expectation that hmacKey be deactivated already.
// Note: This may not be too often the case. We might want to not have deleteHmacKey(String accessId..).
String hmacKeyAccessId = "my-access-id";

storage.deleteHmacKey("my-access-id");

/** Returns an option to specify the Project ID for this request. If not specified,
* defaults to Application Default Credentials.
*/
public static UpdateHmacKeyOption projectId(String projectId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't necessary please remove it.

/** Returns an option to specify the Project ID for this request. If not specified,
* defaults to Application Default Credentials.
*/
public static DeleteHmacKeyOption projectId(String projectId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove option. Reviewing design again it doesn't make sense. I'd expect a Get, List, and Create requests to provide the projectId for subsequent requests.

Copy link
Contributor

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor nits. Otherwise LGTM.

*
* <pre>{@code
* ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
* HmacKey key = storage.createHmacKey(serviceAccount);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perform a Get request instead of a create.

Copy link
Contributor

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more nit and I'll approve, e.g unused variable.

* <p>Example of listing HMAC keys, specifying project id.
*
* <pre>{@code
* ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serviceAccount isn't used.

@JesseLovelace JesseLovelace merged commit 2b0d5ce into master Aug 14, 2019
@Neenu1995 Neenu1995 deleted the hmacsa branch July 6, 2022 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Storage: HMAC Service Account key support

6 participants