Skip to content

Commit

Permalink
Adding support and examples for AOSS (#216)
Browse files Browse the repository at this point in the history
* Adding x-amzn-content-sha256 header for signed requests

Signed-off-by: Vacha Shah <[email protected]>

* Adding examples in user guide

Signed-off-by: Vacha Shah <[email protected]>

* Adding CHANGELOG entry

Signed-off-by: Vacha Shah <[email protected]>

* Addressing comments

Signed-off-by: Vacha Shah <[email protected]>

* Fixing user guide

Signed-off-by: Vacha Shah <[email protected]>

Signed-off-by: Vacha Shah <[email protected]>
  • Loading branch information
VachaShah authored Jan 22, 2023
1 parent a231a68 commit d38a466
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### Added
- Github workflow for changelog verification ([#172](https://github.com/opensearch-project/opensearch-go/pull/172))
- Add Go Documentation link for the client ([#182](https://github.com/opensearch-project/opensearch-go/pull/182))
- Support for Amazon OpenSearch Serverless ([#216](https://github.com/opensearch-project/opensearch-go/pull/216))

### Dependencies
- Bumps `github.com/stretchr/testify` from 1.8.0 to 1.8.1
Expand Down
79 changes: 57 additions & 22 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
- [User Guide](#user-guide)
- [Example](#example)
- [How to use IAMs as authentication method](#how-to-use-iams-as-authentication-method)
- [Example](#example)
- [Amazon OpenSearch Service](#amazon-opensearch-service)
- [AWS SDK V1](#aws-sdk-v1)
- [AWS SDK V2](#aws-sdk-v2)

# User Guide

Expand Down Expand Up @@ -136,7 +138,7 @@ func main() {

```

## How to use IAMs as authentication method
## Amazon OpenSearch Service

Before starting, we strongly recommend reading the full AWS documentation regarding using IAM credentials to sign
requests to OpenSearch APIs.
Expand Down Expand Up @@ -221,32 +223,39 @@ func main() {

#### AWS SDK V2

Use the AWS SDK v2 for Go to authenticate with Amazon OpenSearch service.

```go
package main

import (
"context"
"io"
"log"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/opensearch-project/opensearch-go/v2/opensearchapi"
opensearch "github.com/opensearch-project/opensearch-go/v2"
opensearchapi "github.com/opensearch-project/opensearch-go/v2/opensearchapi"
requestsigner "github.com/opensearch-project/opensearch-go/v2/signer/awsv2"
)

const endpoint = "" // e.g. https://opensearch-domain.region.com
const endpoint = "" // e.g. https://opensearch-domain.region.com or Amazon OpenSearch Serverless endpoint

func main() {
ctx := context.Background()

cfg, err := config.LoadDefaultConfig(ctx)
awsCfg, err := config.LoadDefaultConfig(ctx,
config.WithRegion("<AWS_REGION>"),
config.WithCredentialsProvider(
getCredentialProvider("<AWS_ACCESS_KEY>", "<AWS_SECRET_ACCESS_KEY>", "<AWS_SESSION_TOKEN>"),
),
)
if err != nil {
log.Fatal(err) // Do not log.fatal in a production ready app.
}

// Create an AWS request Signer and load AWS configuration using default config folder or env vars.
// See https://docs.aws.amazon.com/opensearch-service/latest/developerguide/request-signing.html#request-signing-go
signer, err := requestsigner.NewSigner(cfg)
signer, err := requestsigner.NewSignerWithService(awsCfg, "es") // "aoss" for Amazon OpenSearch Serverless
if err != nil {
log.Fatal(err) // Do not log.fatal in a production ready app.
}
Expand All @@ -260,26 +269,52 @@ func main() {
log.Fatal("client creation err", err)
}

ping := opensearchapi.PingRequest{}
indexName = "go-test-index"

resp, err := ping.Do(ctx, client)
// Define index mapping.
mapping := strings.NewReader(`{
"settings": {
"index": {
"number_of_shards": 4
}
}
}`)

// Create an index with non-default settings.
createIndex := opensearchapi.IndicesCreateRequest{
Index: indexName,
Body: mapping,
}
createIndexResponse, err := createIndex.Do(context.Background(), client)
if err != nil {
log.Fatal(err)
log.Println("Error ", err.Error())
log.Println("failed to create index ", err)
log.Fatal("create response body read err", err)
}
defer resp.Body.Close()
log.Println(createIndexResponse)

if resp.IsError() {
log.Println("ping response status ", resp.Status())

respBody, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal("response body read err", err)
}
// Delete previously created index.
deleteIndex := opensearchapi.IndicesDeleteRequest{
Index: []string{indexName},
}

log.Fatal("ping resp body", respBody)
deleteIndexResponse, err := deleteIndex.Do(context.Background(), client)
if err != nil {
log.Println("failed to delete index ", err)
log.Fatal("delete index response body read err", err)
}
log.Println("deleting index", deleteIndexResponse)
}

log.Println("PING OK")
func getCredentialProvider(accessKey, secretAccessKey, token string) aws.CredentialsProviderFunc {
return func(ctx context.Context) (aws.Credentials, error) {
c := &aws.Credentials{
AccessKeyID: accessKey,
SecretAccessKey: secretAccessKey,
SessionToken: token,
}
return *c, nil
}
}

```
1 change: 1 addition & 0 deletions signer/awsv2/sdkv2signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func (s *awsSdkV2Signer) SignRequest(r *http.Request) error {
}

hash, err := hexEncodedSha256OfRequest(r)
r.Header.Set("X-Amz-Content-Sha256", hash)
if err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions signer/awsv2/sdkv2signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func TestV4SignerAwsSdkV2(t *testing.T) {
q := req.Header
assert.NotEmpty(t, q.Get("Authorization"))
assert.NotEmpty(t, q.Get("X-Amz-Date"))
assert.NotEmpty(t, q.Get("X-Amz-Content-Sha256"))
})
t.Run("sign request success with body", func(t *testing.T) {
req, err := http.NewRequest(
Expand Down Expand Up @@ -109,6 +110,7 @@ func TestV4SignerAwsSdkV2(t *testing.T) {
q := req.Header
assert.NotEmpty(t, q.Get("Authorization"))
assert.NotEmpty(t, q.Get("X-Amz-Date"))
assert.NotEmpty(t, q.Get("X-Amz-Content-Sha256"))
})

t.Run("sign request success with body for other AWS Services", func(t *testing.T) {
Expand Down Expand Up @@ -139,6 +141,7 @@ func TestV4SignerAwsSdkV2(t *testing.T) {
q := req.Header
assert.NotEmpty(t, q.Get("Authorization"))
assert.NotEmpty(t, q.Get("X-Amz-Date"))
assert.NotEmpty(t, q.Get("X-Amz-Content-Sha256"))
})

t.Run("sign request failed due to invalid service", func(t *testing.T) {
Expand Down

0 comments on commit d38a466

Please sign in to comment.