Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
92e8b1e
chore: update version, description and author
rahulreddy Apr 23, 2018
109ca1f
chore: update scality dependencies
rahulreddy Apr 23, 2018
a6265ab
ft: edit usage of uid on buckets
philipyoo Apr 9, 2018
d6e8201
ft: ZENKO-229 get obj based on location
dora-korpar Apr 6, 2018
35d12ea
Merge pull request #1199 from scality/ft/S3C-1391-update-bucketinfo-uid
nicolas2bert Apr 24, 2018
1fd51c8
ft: ZENKO-141 allows MongoDB/metadata Scality/data
Apr 24, 2018
6d67e98
rf: ZENKO-250 port md search test
alexanderchan-scality Apr 18, 2018
9e1e00c
Merge pull request #1218 from scality/rf/ZENKO-250-portmdsearchtest
rahulreddy Apr 25, 2018
6ef23a0
Merge pull request #1228 from scality/ft/ZENKO-141-scality-dataserver
rahulreddy Apr 25, 2018
d02dbeb
FIX: Do not include untrimmed headers
Mar 20, 2018
d52762c
Merge pull request #1204 from scality/ft/ZENKO-229-get-using-location
nicolas2bert Apr 25, 2018
d759593
Merge pull request #1175 from scality/fix/do-not-include-untrimmed-he…
nicolas2bert Apr 25, 2018
35f457d
ft: ZENKO-262 preferred read/write locations
alexanderchan-scality Apr 25, 2018
0b9b203
bf: ZENKO-275 CRR to GCP MPU properties
Apr 24, 2018
8a291ca
Merge pull request #1229 from scality/bf/ZENKO-275/mpuPropertiesGCP
nicolas2bert Apr 27, 2018
b603463
Merge pull request #1227 from scality/ft/ZENKO-262-preferredReadWiteL…
rahulreddy Apr 27, 2018
399ecf5
rf: S3C-1399 Update Redis configuration
Apr 20, 2018
0ae1175
doc: ZENKO-259 mdsearch
alexanderchan-scality Apr 25, 2018
e7a1ab2
Merge pull request #1223 from scality/rf/S3C-1399/updateRedisConfig
rahulreddy Apr 27, 2018
5d71417
Merge pull request #1220 from scality/doc/ZENKO-259-mdsearch
rahulreddy Apr 27, 2018
ba820e5
bf: ZENKO-250 correctly evaluate regex pattern
alexanderchan-scality Apr 25, 2018
6722336
rf: S3C-1399 Use CRR metrics from Arsenal
Apr 19, 2018
a79b5de
Merge pull request #1232 from scality/bf/ZENKO-250-regexEval
rahulreddy Apr 30, 2018
a011400
Merge pull request #1225 from scality/rf/S3C-1399/refactor-backbeat-m…
nicolas2bert Apr 30, 2018
2e4234e
bf: ZENKO-332 fix Azure proxy localhost req
dora-korpar May 11, 2018
ea9645c
Merge pull request #1243 from scality/bf/ZENKO-332-azure-proxy
rahulreddy May 11, 2018
3f7add2
fix: use existing localCache redis configuration
rachedbenmustapha May 11, 2018
56e60ab
Merge pull request #1244 from scality/fix/ZENKO-345-unduplicate-redis…
rachedbenmustapha May 12, 2018
f2f2a5e
bf: ZENKO-349 add mongodb metadata env
alexanderchan-scality May 12, 2018
f5132b9
bf: ZENKO-350 add MD search validation
alexanderchan-scality May 12, 2018
4aaca47
ft: ZENKO-347 skip MongoDB version listing
alexanderchan-scality May 12, 2018
08d9e6f
Merge pull request #1247 from scality/bf/ZENKO-350-addMDSearchValidation
rahulreddy May 13, 2018
d77ff38
Merge pull request #1248 from scality/ft/ZENKO-347-skipMongoDbListing…
rahulreddy May 13, 2018
d88f042
test: Orbit management
nicolas2bert Apr 23, 2018
024544b
Merge pull request #1233 from scality/test/orbit-management
rahulreddy May 15, 2018
0b85e45
ft: ZENKO-347 skip MongoDB version listing
alexanderchan-scality May 16, 2018
67eb20c
bf: ZENKO-314 add check for max keys zero object listing
alexanderchan-scality May 8, 2018
0712aa4
Merge pull request #1241 from scality/bf/ZENKO-314-maxKeysZero
rahulreddy May 17, 2018
acb5d72
bf: receive/send crr metrics sizes as bytes
philipyoo May 15, 2018
84e97d1
bf: ignore gem install digest
philipyoo May 23, 2018
d758edd
Merge pull request #1250 from scality/bf/ZENKO-355-byteToMBConversion
rahulreddy May 23, 2018
9af917e
bf: lock node-http-mocks module
rahulreddy May 25, 2018
7ac9ac6
Merge pull request #1256 from scality/bf/lockMocksModule
rahulreddy May 25, 2018
0025bdd
Merge remote-tracking branch 'origin/z/1.0' into fwdport/z/1.0-master
rahulreddy May 29, 2018
518e8c4
chore: use master dependency branches
rahulreddy May 29, 2018
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
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dependencies:
- gem install mime-types -v 3.1
- gem install rspec -v 3.5
- gem install json
- gem install digest
# - gem install digest
# java sdk dependencies
- sudo apt-get install -y -q default-jdk

Expand Down
4 changes: 3 additions & 1 deletion dataserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ const logger = require('./lib/utilities/logger');

if (config.backends.data === 'file' ||
(config.backends.data === 'multiple' &&
config.backends.metadata !== 'scality')) {
config.backends.metadata !== 'scality') &&
(config.backends.auth !== 'scality' &&
config.backends.metadata !== 'mongodb')) {
const dataServer = new arsenal.network.rest.RESTServer(
{ bindAddress: config.dataDaemon.bindAddress,
port: config.dataDaemon.port,
Expand Down
229 changes: 229 additions & 0 deletions docs/MD_SEARCH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# Metadata Search Documenation

## Description

This feature enables metadata search to be performed on the metadata of objects
stored in Zenko.

## Requirements

+ MongoDB

## Design

The MD Search feature expands on the existing `GET Bucket` S3 API. It allows
users to conduct metadata searches by adding the custom Zenko querystring
parameter, `search`. The `search` parameter is of a pseudo
SQL WHERE clause structure and supports basic SQL operators:
ex. `"A=1 AND B=2 OR C=3"` (more complex queries can also be achieved with the
use of nesting operators, `(` and `)`).

The search process is as follows:

+ Zenko receives a `GET` request.

```
# regular getBucket request
GET /bucketname HTTP/1.1
Host: 127.0.0.1:8000
Date: Wed, 18 Oct 2018 17:50:00 GMT
Authorization: authorization string

# getBucket versions request
GET /bucketname?versions HTTP/1.1
Host: 127.0.0.1:8000
Date: Wed, 18 Oct 2018 17:50:00 GMT
Authorization: authorization string

# search getBucket request
GET /bucketname?search=key%3Dsearch-item HTTP/1.1
Host: 127.0.0.1:8000
Date: Wed, 18 Oct 2018 17:50:00 GMT
Authorization: authorization string
```

+ If the request does not contain the query param `search`, a normal bucket
listing is performed and a XML result containing the list of objects will be
returned as the response.
+ If the request does contain the query parameter `search`, the search string is
parsed and validated.

+ If the search string is invalid, an `InvalidArgument` error will be
returned as response.
+ If the search string is valid, it will be parsed and an abstract syntax
tree (AST) is generated.

+ The AST is then passed to the MongoDB backend to be used as the query filter
for retrieving objects in a bucket that satisfies the requested search
conditions.
+ The filtered results are then parsed and returned as the response.

The results from MD search is of the same structure as the `GET Bucket`
results:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>bucketname</Name>
<Prefix/>
<Marker/>
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>objectKey</Key>
<LastModified>2018-04-19T18:31:49.426Z</LastModified>
<ETag>&quot;d41d8cd98f00b204e9800998ecf8427e&quot;</ETag>
<Size>0</Size>
<Owner>
<ID>79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be</ID>
<DisplayName>Bart</DisplayName>
</Owner>
<StorageClass>STANDARD</StorageClass>
</Contents>
<Contents>
...
</Contents>
</ListBucketResult>
```

## Performing MD Search with Zenko

To make a successful request to Zenko, you would need

+ Zenko Credentials
+ Sign request with Auth V4

With requirements, you can peform metadata searches by:

+ using the `search_bucket` tool in the
[Scality/S3](https://github.com/scality/S3) GitHub repository.
+ creating an AuthV4 signed HTTP request to Zenko in the programming language of
choice

### Using the S3 Tool

After cloning the [Scality/S3](https://github.com/scality/S3) GitHub repository
and installing the necessary dependencies, you can run the following command
in the S3 project root directory to access the search tool.

```
node bin/search_bucket
```

This will generate the following output

```
Usage: search_bucket [options]

Options:

-V, --version output the version number
-a, --access-key <accessKey> Access key id
-k, --secret-key <secretKey> Secret access key
-b, --bucket <bucket> Name of the bucket
-q, --query <query> Search query
-h, --host <host> Host of the server
-p, --port <port> Port of the server
-s --ssl
-v, --verbose
-h, --help output usage information
```

In the following examples, our Zenko Server is accessible on endpoint
`http://127.0.0.1:8000` and contains the bucket `zenkobucket`.

```
# search for objects with metadata "blue"
node bin/search_bucket -a accessKey1 -k verySecretKey1 -b zenkobucket \
-q "x-amz-meta-color=blue" -h 127.0.0.1 -p 8000

# search for objects tagged with "type=color"
node bin/search_bucket -a accessKey1 -k verySecretKey1 -b zenkobucket \
-q "tags.type=color" -h 127.0.0.1 -p 8000
```

### Coding Examples

Search requests can be also performed by making HTTP requests authenticated
with the `AWS Signature version 4` scheme.\
See the following urls for more information about the V4 authentication scheme.

+ http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+ http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

You can also view examples for making requests with Auth V4 in various
languages [here](../exmaples).

### Specifying Metadata Fields

To search common metadata headers:

```
{metadata-key}{supported SQL op}{search value}
# example
key = blueObject
size > 0
key LIKE "blue.*"
```

To search custom user metadata:

```
# metadata must be prefixed with "x-amz-meta-"
x-amz-meta-{usermetadata-key}{supported SQL op}{search value}
# example
x-amz-meta-color = blue
x-amz-meta-color != red
x-amz-meta-color LIKE "b.*"
```

To search tags:

```
# tag searches must be prefixed with "tags."
tags.{tag-key}{supported SQL op}{search value}
# example
tags.type = color
```

### Differences from SQL

The MD search queries are similar to the `WHERE` clauses of SQL queries, but
they differ in that:

+ MD search queries follow the `PCRE` format
+ Search queries do not require values with hyphens to be enclosed in
backticks, ``(`)``

```
# SQL query
`x-amz-meta-search-item` = `ice-cream-cone`

# MD Search query
x-amz-meta-search-item = ice-cream-cone
```

+ The search queries do not support all of the SQL operators.

+ Supported SQL Operators: `=`, `<`, `>`, `<=`, `>=`, `!=`,
`AND`, `OR`, `LIKE`, `<>`
+ Unsupported SQL Operators: `NOT`, `BETWEEN`, `IN`, `IS`, `+`,
`-`, `%`, `^`, `/`, `*`, `!`

#### Using Regular Expressions in MD Search

+ Regular expressions used in MD search differs from SQL in that wildcards are
represented with `.*` instead of `%`.
+ Regex patterns must be wrapped in quotes as not doing so can lead to
misinterpretation of patterns.
+ Regex patterns can be written in form of the `/pattern/` syntax or
just the pattern if one does not require regex options, similar to `PCRE`.

Example regular expressions:

```
# search for strings containing word substring "helloworld"
".*helloworld.*"
"/.*helloworld.*/"
"/.*helloworld.*/i"
```
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
# http://www.mkdocs.org/user-guide/configuration/
# https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes

Expand Down
46 changes: 46 additions & 0 deletions examples/go-md-search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

import (
"fmt"
"time"
"bytes"
"net/http"
"net/url"
"io/ioutil"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/signer/v4"
)

func main() {
// Input AWS access key, secret key
aws_access_key_id := "accessKey1"
aws_secret_access_key := "verySecretKey1"
endpoint := "http://localhost:8000"
bucket_name := "bucketname"
searchQuery := url.QueryEscape("x-amz-meta-color=blue")
buf := bytes.NewBuffer([]byte{})

requestUrl := fmt.Sprintf("%s/%s?search=%s",
endpoint, bucket_name, searchQuery)

request, err := http.NewRequest("GET", requestUrl, buf)
if err != nil {
panic(err)
}
reader := bytes.NewReader(buf.Bytes())
credentials := credentials.NewStaticCredentials(aws_access_key_id,
aws_secret_access_key, "")
signer := v4.NewSigner(credentials)
signer.Sign(request, reader, "s3", "us-east-1", time.Now())
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
28 changes: 28 additions & 0 deletions examples/node-md-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const { S3 } = require('aws-sdk');
const config = {
sslEnabled: false,
endpoint: 'http://127.0.0.1:8000',
signatureCache: false,
signatureVersion: 'v4',
region: 'us-east-1',
s3ForcePathStyle: true,
accessKeyId: 'accessKey1',
secretAccessKey: 'verySecretKey1',
};
const s3Client = new S3(config);

const encodedSearch =
encodeURIComponent('x-amz-meta-color="blue"');
const req = s3Client.listObjects({ Bucket: 'bucketname' });

// the build event
req.on('build', () => {
req.httpRequest.path = `${req.httpRequest.path}?search=${encodedSearch}`;
});
req.on('success', res => {
process.stdout.write(`Result ${res.data}`);
});
req.on('error', err => {
process.stdout.write(`Error ${err}`);
});
req.send();
Loading