Skip to content

Add read-only repository verification #35731

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

Merged
merged 4 commits into from
Nov 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- do:
snapshot.create_repository:
repository: test_repo1
verify: false
body:
type: url
settings:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,12 @@

package org.elasticsearch.repositories.s3;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion;
import com.amazonaws.services.s3.model.HeadBucketRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.model.StorageClass;

import org.elasticsearch.common.blobstore.BlobContainer;
import org.elasticsearch.common.blobstore.BlobPath;
import org.elasticsearch.common.blobstore.BlobStore;
Expand Down Expand Up @@ -63,29 +60,6 @@ class S3BlobStore implements BlobStore {
this.bufferSize = bufferSize;
this.cannedACL = initCannedACL(cannedACL);
this.storageClass = initStorageClass(storageClass);

// Note: the method client.doesBucketExist() may return 'true' is the bucket exists
// but we don't have access to it (ie, 403 Forbidden response code)
try (AmazonS3Reference clientReference = clientReference()) {
SocketAccess.doPrivilegedVoid(() -> {
try {
clientReference.client().headBucket(new HeadBucketRequest(bucket));
} catch (final AmazonServiceException e) {
if (e.getStatusCode() == 301) {
throw new IllegalArgumentException("the bucket [" + bucket + "] is in a different region than you configured", e);
} else if (e.getStatusCode() == 403) {
throw new IllegalArgumentException("you do not have permissions to access the bucket [" + bucket + "]", e);
} else if (e.getStatusCode() == 404) {
throw new IllegalArgumentException(
"the bucket [" + bucket + "] does not exist;"
+ " please create it before creating an S3 snapshot repository backed by it",
e);
} else {
throw new IllegalArgumentException("error checking the existence of bucket [" + bucket + "]", e);
}
}
});
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,13 @@
package org.elasticsearch.repositories.s3;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AbstractAmazonS3;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.DeleteObjectsResult;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.HeadBucketRequest;
import com.amazonaws.services.s3.model.HeadBucketResult;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
Expand Down Expand Up @@ -75,18 +72,6 @@ class MockAmazonS3 extends AbstractAmazonS3 {
this.storageClass = storageClass;
}

@Override
public HeadBucketResult headBucket(final HeadBucketRequest headBucketRequest) throws SdkClientException, AmazonServiceException {
if (this.bucket.equalsIgnoreCase(headBucketRequest.getBucketName())) {
return new HeadBucketResult();
} else {
final AmazonServiceException e =
new AmazonServiceException("bucket [" + headBucketRequest.getBucketName() + "] does not exist");
e.setStatusCode(404);
throw e;
}
}

@Override
public boolean doesObjectExist(final String bucketName, final String objectName) throws SdkClientException {
assertThat(bucketName, equalTo(bucket));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,9 @@

package org.elasticsearch.repositories.s3;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.HeadBucketRequest;
import com.amazonaws.services.s3.model.HeadBucketResult;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
Expand Down Expand Up @@ -63,11 +58,6 @@ static final class ClientAndCredentials extends AmazonS3Wrapper {
this.credentials = credentials;
}

@Override
public HeadBucketResult headBucket(HeadBucketRequest headBucketRequest) throws AmazonClientException, AmazonServiceException {
return new HeadBucketResult();
}

}

static final class ProxyS3Service extends S3Service {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@

package org.elasticsearch.repositories.s3;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AbstractAmazonS3;
import com.amazonaws.services.s3.model.HeadBucketRequest;
import com.amazonaws.services.s3.model.HeadBucketResult;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
Expand All @@ -45,11 +41,6 @@ public class S3RepositoryTests extends ESTestCase {

private static class DummyS3Client extends AbstractAmazonS3 {

@Override
public HeadBucketResult headBucket(final HeadBucketRequest request) throws SdkClientException, AmazonServiceException {
return new HeadBucketResult();
}

@Override
public void shutdown() {
// TODO check is closed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ setup:
"Register a repository with a non existing bucket":

- do:
catch: /repository_exception/
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_permanent
body:
Expand All @@ -197,7 +197,7 @@ setup:
"Register a repository with a non existing client":

- do:
catch: /repository_exception/
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_permanent
body:
Expand All @@ -206,6 +206,34 @@ setup:
bucket: repository_permanent
client: unknown

---
"Register a read-only repository with a non existing bucket":

- do:
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_permanent
body:
type: s3
settings:
readonly: true
bucket: zHHkfSqlbnBsbpSgvCYtxrEfFLqghXtyPvvvKPNBnRCicNHQLE
client: integration_test_permanent

---
"Register a read-only repository with a non existing client":

- do:
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_permanent
body:
type: s3
settings:
readonly: true
bucket: repository_permanent
client: unknown

---
"Get a non existing snapshot":

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ setup:
"Register a repository with a non existing bucket":

- do:
catch: /repository_exception/
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_temporary
body:
Expand All @@ -197,7 +197,7 @@ setup:
"Register a repository with a non existing client":

- do:
catch: /repository_exception/
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_temporary
body:
Expand All @@ -206,6 +206,34 @@ setup:
bucket: repository_temporary
client: unknown

---
"Register a read-only repository with a non existing bucket":

- do:
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_temporary
body:
type: s3
settings:
readonly: true
bucket: zHHkfSqlbnBsbpSgvCYtxrEfFLqghXtyPvvvKPNBnRCicNHQLE
client: integration_test_temporary

---
"Register a read-only repository with a non existing client":

- do:
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_temporary
body:
type: s3
settings:
readonly: true
bucket: repository_temporary
client: unknown

---
"Get a non existing snapshot":

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ setup:
"Register a repository with a non existing bucket":

- do:
catch: /repository_exception/
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_ec2
body:
Expand All @@ -197,7 +197,7 @@ setup:
"Register a repository with a non existing client":

- do:
catch: /repository_exception/
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_ec2
body:
Expand All @@ -206,6 +206,34 @@ setup:
bucket: repository_ec2
client: unknown

---
"Register a read-only repository with a non existing bucket":

- do:
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_ec2
body:
type: s3
settings:
readonly: true
bucket: zHHkfSqlbnBsbpSgvCYtxrEfFLqghXtyPvvvKPNBnRCicNHQLE
client: integration_test_temporary

---
"Register a read-only repository with a non existing client":

- do:
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_ec2
body:
type: s3
settings:
readonly: true
bucket: repository_ec2
client: unknown

---
"Get a non existing snapshot":

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,20 @@ setup:
"Register a repository with a non existing bucket":

- do:
catch: /repository_exception/
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_ecs
body:
type: s3
settings:
bucket: zHHkfSqlbnBsbpSgvCYtxrEfFLqghXtyPvvvKPNBnRCicNHQLE
client: integration_test_temporary
client: integration_test_ecs

---
"Register a repository with a non existing client":

- do:
catch: /repository_exception/
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_ecs
body:
Expand All @@ -206,6 +206,34 @@ setup:
bucket: repository_ecs
client: unknown

---
"Register a read-only repository with a non existing bucket":

- do:
catch: /repository_verification_exception/
snapshot.create_repository:
repository: repository_ecs
body:
type: s3
settings:
readonly: true
bucket: zHHkfSqlbnBsbpSgvCYtxrEfFLqghXtyPvvvKPNBnRCicNHQLE
client: integration_test_ecs

---
"Register a read-only repository with a non existing client":

- do:
catch: /illegal_argument_exception/
snapshot.create_repository:
repository: repository_ecs
body:
type: s3
settings:
readonly: true
bucket: repository_ecs
client: unknown

---
"Get a non existing snapshot":

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ setup:
body:
type: fs
settings:
readonly: true
location: "test_repo_get_1_loc"

---
Expand Down Expand Up @@ -51,6 +52,12 @@ setup:

---
"Verify created repository":
- do:
snapshot.verify_repository:
repository: test_repo_get_1

- is_true: nodes

- do:
snapshot.verify_repository:
repository: test_repo_get_2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,14 @@ public boolean mustAck(DiscoveryNode discoveryNode) {

public void verifyRepository(final String repositoryName, final ActionListener<VerifyResponse> listener) {
final Repository repository = repository(repositoryName);
final boolean readOnly = repository.isReadOnly();
try {
threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(() -> {
try {
final String verificationToken = repository.startVerification();
if (verificationToken != null) {
try {
verifyAction.verify(repositoryName, verificationToken, new ActionListener<VerifyResponse>() {
verifyAction.verify(repositoryName, readOnly, verificationToken, new ActionListener<VerifyResponse>() {
@Override
public void onResponse(VerifyResponse verifyResponse) {
threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(() -> {
Expand Down
Loading