Skip to content
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

Update s3 secure settings #28517

Conversation

albertzaharovits
Copy link
Contributor

@albertzaharovits albertzaharovits commented Feb 5, 2018

Secure settings for the S3 repository plugin are update-able.
AWSS3 clients have to be requested from the InternalAwsS3Service service for each use. These client instances cannot be stored and used at a later time because they can change if their settings change. The client request and client update logic is protected by a read-write lock.

TODOs:

  • fix existing tests
  • add tests for reload credentials
  • fail if removing settings in use by the repository ?
  • keep existing settings override from cluster settings ?

Copy link
Contributor

@s1monw s1monw left a comment

Choose a reason for hiding this comment

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

I like it. I left some comments


private final Map<String, S3ClientSettings> clientsSettings;
private final ReadWriteLock lock;
private final ConcurrentHashMap<String, AmazonS3> clientsCache;
Copy link
Contributor

Choose a reason for hiding this comment

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

lets make this an immutable map instead. That way we don't need a read-write lock and can just make the method that changes the reference synchronized. Also for the AmazonS3Wrapper we can just use a reference counter. We already have the infrastructure for it in org.elasticsearch.common.util.concurrent.AbstractRefCounted lemme know if you need help with this.

public void updateClientSettings(Settings settings) {
lock.writeLock().lock();
try {
// clear previously cached clients
Copy link
Contributor

Choose a reason for hiding this comment

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

++ I like that we completely destroy it once we are refreshing the settings.

} catch (AmazonClientException e) {
throw new IOException("Exception when deleting blob [" + blobName + "]", e);
}
}

@Override
public Map<String, BlobMetaData> listBlobsByPrefix(@Nullable String blobNamePrefix) throws IOException {
return AccessController.doPrivileged((PrivilegedAction<Map<String, BlobMetaData>>) () -> {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we please not change the way we use AccessController here. We can do this in a sep. change but this is a cause of trouble and hard to understand why it's needed if at all

@clintongormley clintongormley added :Distributed Coordination/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs and removed :Plugin Repository S3 labels Feb 14, 2018
@albertzaharovits
Copy link
Contributor Author

@s1monw I have addressed your feedback.
The client cache is a volatile reference to an immutable map.
Also, AmazonS3Wrapperinterface extends RefCounted and Releasable. The implementation extends AbstractRefCount. The Releasable#close methods is a proxy for RefCounted#decRef so it's not really required ,but it's nice because it allows the usage inside try/with blocks.

@albertzaharovits
Copy link
Contributor Author

albertzaharovits commented Feb 16, 2018

@s1monw this is ready for another review round. Can you please take a look?
If you agree with the approach I will update the tests as well.

Copy link
Contributor

@s1monw s1monw left a comment

Choose a reason for hiding this comment

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

left some comments. The approach is good IMO

return client;
public synchronized void updateClientSettings(Settings settings) {
// the clients will shutdown when they will not be used anymore
for (final AmazonS3Wrapper clientWrapper : clientsCache.values()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can u use Releasables#close here instead of a loop.

// clear previously cached clients
clientsCache = Collections.unmodifiableMap(emptyMap());
// reload secure settings
clientsSettings = Collections.unmodifiableMap(S3ClientSettings.load(settings));
Copy link
Contributor

Choose a reason for hiding this comment

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

leave a comment here that we built the clients lazily

}
// clear previously cached clients
clientsCache = Collections.unmodifiableMap(emptyMap());
Copy link
Contributor

Choose a reason for hiding this comment

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

Collections.emptyMap() is already immutable

@@ -174,4 +166,30 @@ public void refresh() {
SocketAccess.doPrivilegedVoid(credentials::refresh);
}
}

private static class InternalAmazonS3Wrapper extends AbstractRefCounted implements AmazonS3Wrapper {
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 we need the AmazonS3Wrapper interface just make this class public and name it AmazonS3Wrapper

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd call it AmazonS3Reference

@albertzaharovits
Copy link
Contributor Author

albertzaharovits commented Mar 12, 2018

@s1monw I think this deserves another round of review. May you look into it, please?

There are quite a few changes, few of them overflowing more than you'd like on a bad day.
Most changes were required to separate client settings parsing (from node secure settings and cluster state) from building and caching the clients using those settings. I think the client cache allowing for update-able settings (InternalAwsS3Service) can be cherry-pick-ed in other places now (it will require some generics enrichment at least).
Other minor changes are for testing purposes (RepositoryCredentialsTests) since some of the new functionality is buried deeper and required some mocking to be constructed.

Lastly, I think tests are patchy and it is not clear what code paths they cover but I also think changes there fit in a separate PR(s).

Copy link
Contributor

@s1monw s1monw left a comment

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Distributed Coordination/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs >feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants