-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Storage: HMAC service account support #5284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| } | ||
|
|
||
| public static class Builder { | ||
| private String secretKey; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not super familiar with documenting Java code, but can we add a note saying the secret is only available on creation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah--I'm planning to add the documentation once the code is otherwise approved
jkwlui
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra space here?
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, would need "HmacKey.HmacKeyMetadata" without it
| */ | ||
| List<ObjectAccessControl> listAcls(String bucket, String object, Long generation); | ||
|
|
||
| HmacKey createHmacKey(String serviceAccountEmail); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the introduction of these new RPCs the NIO library will also need to be updated. https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-nio
| @Test | ||
| public void testHmacKey() { | ||
| ServiceAccount serviceAccount = | ||
| ServiceAccount.of("[email protected]"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, would need "HmacKey.HmacKeyMetadata" without it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, gotcha. Thanks for clarifying!
|
|
||
| void deleteHmacKey(String accessId); | ||
|
|
||
| HmacKeyMetadata updateHmacKeyState( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, why the overload for showDeletedKeys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha that makes sense. What about defaulting to not showing deleted keys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is already the default I believe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API defaults to false if not given.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @jkwlui and @JesseLovelace!
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
| * | ||
| * @throws StorageException upon failure | ||
| */ | ||
| Page<HmacKeyMetadata> listHmacKeys(ServiceAccount serviceAccount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
listHmacKeys should also be able to accept no serviceAccount, which will show HMAC keys from all accounts. Can your implementation accept no serviceAccount?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Listing keys from all accounts can be accomplished by calling this with serviceAccount=null. I'll add a note about it in the documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. That would really help, thank you!
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include options for userProject.
| * | ||
| * @throws StorageException upon failure | ||
| */ | ||
| HmacKeyMetadata getHmacKey(String accessId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include options for userProject.
| * | ||
| * @throws StorageException upon failure | ||
| */ | ||
| void deleteHmacKey(String accessId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include options for userProject.
| * @throws StorageException upon failure | ||
| */ | ||
| HmacKeyMetadata updateHmacKeyState( | ||
| final HmacKeyMetadata hmacKeyMetadata, final HmacKey.HmacKeyState state); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include options for userProject.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few last nits. Thank you for your patience.
| * | ||
| * @throws StorageException upon failure | ||
| */ | ||
| void deleteHmacKey(String accessId, DeleteHmacKeyOption... options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor nits. Otherwise LGTM.
google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
Show resolved
Hide resolved
google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
Show resolved
Hide resolved
...ients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java
Show resolved
Hide resolved
| * | ||
| * <pre>{@code | ||
| * ServiceAccount serviceAccount = ServiceAccount.of("[email protected]"); | ||
| * HmacKey key = storage.createHmacKey(serviceAccount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perform a Get request instead of a create.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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]"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serviceAccount isn't used.
Fixes #5054
Adds support for HMAC service accounts. Holding off on adding documentation until the general implementation is approved