Skip to content

Commit

Permalink
connects guac with a given aws neptune cluster endpoint (#1126)
Browse files Browse the repository at this point in the history
Signed-off-by: stevemenezes <steve.menezes@yahooinc.com>
  • Loading branch information
stevemenezes committed Aug 4, 2023
1 parent c0614ec commit bc5c042
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 9 deletions.
18 changes: 16 additions & 2 deletions cmd/guacgql/cmd/root.go
Expand Up @@ -44,6 +44,13 @@ var flags = struct {
arangoAddr string
arangoUser string
arangoPass string

// Needed only if using neptune backend
neptuneEndpoint string
neptunePort int
neptuneRegion string
neptuneUser string
neptuneRealm string
}{}

var rootCmd = &cobra.Command{
Expand All @@ -66,6 +73,12 @@ var rootCmd = &cobra.Command{
flags.arangoPass = viper.GetString("arango-pass")
flags.arangoAddr = viper.GetString("arango-addr")

flags.neptuneEndpoint = viper.GetString("neptune-endpoint")
flags.neptunePort = viper.GetInt("neptune-port")
flags.neptuneRegion = viper.GetString("neptune-region")
flags.neptuneUser = viper.GetString("neptune-user")
flags.neptuneRealm = viper.GetString("neptune-realm")

startServer(cmd)
},
}
Expand All @@ -75,8 +88,9 @@ func init() {

set, err := cli.BuildFlags([]string{
"arango-addr", "arango-user", "arango-pass",
"neo4j-addr", "neo4j-user", "neo4j-pass", "neo4j-realm", "gql-test-data",
"gql-listen-port", "gql-debug", "gql-backend", "gql-trace"})
"neo4j-addr", "neo4j-user", "neo4j-pass", "neo4j-realm",
"neptune-endpoint", "neptune-port", "neptune-region", "neptune-user", "neptune-realm",
"gql-test-data", "gql-listen-port", "gql-debug", "gql-backend", "gql-trace"})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to setup flag: %v", err)
os.Exit(1)
Expand Down
89 changes: 85 additions & 4 deletions cmd/guacgql/cmd/server.go
Expand Up @@ -17,6 +17,7 @@ package cmd

import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
Expand All @@ -27,6 +28,9 @@ import (
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/debug"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/spf13/cobra"

"github.com/guacsec/guac/pkg/assembler/backends/arangodb"
Expand All @@ -38,9 +42,12 @@ import (
)

const (
arango = "arango"
neo4js = "neo4j"
inmems = "inmem"
arango = "arango"
neo4js = "neo4j"
inmems = "inmem"
neptune = "neptune"

neptuneServiceName = "neptune-db"
)

func startServer(cmd *cobra.Command) {
Expand Down Expand Up @@ -104,7 +111,7 @@ func startServer(cmd *cobra.Command) {

func validateFlags() error {
if flags.backend != neo4js &&
flags.backend != inmems && flags.backend != arango {
flags.backend != inmems && flags.backend != arango && flags.backend != neptune {
return fmt.Errorf("invalid graphql backend specified: %v", flags.backend)
}
return nil
Expand Down Expand Up @@ -149,6 +156,28 @@ func getGraphqlServer(ctx context.Context) (*handler.Server, error) {
return nil, fmt.Errorf("error creating inmem backend: %w", err)
}

topResolver = resolvers.Resolver{Backend: backend}

case neptune:
// TODO: rename the neo4j config to something more generic since it would be used by Neptune as well.
neptuneRequestURL := fmt.Sprintf("https://%s:%d/opencypher", flags.neptuneEndpoint, flags.neptunePort)
neptuneToken, err := generateNeptuneToken(neptuneRequestURL, flags.neptuneRegion)
if err != nil {
return nil, fmt.Errorf("failed to create password for neptune: %w", err)
}

neptuneDBAddr := fmt.Sprintf("bolt+s://%s:%d/opencypher", flags.neptuneEndpoint, flags.neptunePort)
args := neo4j.Neo4jConfig{
User: flags.neptuneUser,
Pass: neptuneToken,
DBAddr: neptuneDBAddr,
Realm: flags.neptuneRealm,
}
backend, err := neo4j.GetBackend(&args)
if err != nil {
return nil, fmt.Errorf("error creating neptune backend: %w", err)
}

topResolver = resolvers.Resolver{Backend: backend}
default:
return nil, fmt.Errorf("invalid backend specified: %v", flags.backend)
Expand All @@ -164,3 +193,55 @@ func healthHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "Server is healthy")
}

// generateNeptuneToken generates a token for neptune using the AWS SDK.
func generateNeptuneToken(neptuneURL string, region string) (string, error) {
req, err := http.NewRequest(http.MethodGet, neptuneURL, nil)
if err != nil {
return "", fmt.Errorf("error creating http request for neptune: %w", err)
}

signer, err := getAWSRequestSigner()
if err != nil {
return "", fmt.Errorf("error creating AWS request signer: %w", err)
}

if _, err := signer.Sign(req, nil, neptuneServiceName, region, time.Now()); err != nil {
return "", fmt.Errorf("error signing neptune request: %w", err)
}

headers := []string{"Authorization", "X-Amz-Date", "X-Amz-Security-Token"}
hdrMap := make(map[string]string)
for _, h := range headers {
hdrMap[h] = req.Header.Get(h)
}

hdrMap["Host"] = req.Host
hdrMap["HttpMethod"] = req.Method
password, err := json.Marshal(hdrMap)
if err != nil {
return "", fmt.Errorf("error marshalling header map: %w", err)
}

return string(password), nil
}

// This method returns the AWS signer to be used for signing the request to be sent to Neptune Cluster.
// It checks for the presence of AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN in the environment.
// If not found, it creates a new session and gets the credentials from the session.
func getAWSRequestSigner() (*v4.Signer, error) {
accessKeyID := os.Getenv("AWS_ACCESS_KEY_ID")
secretAccessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
sessionToken := os.Getenv("AWS_SESSION_TOKEN")

if accessKeyID != "" && secretAccessKey != "" && sessionToken != "" {
return v4.NewSigner(credentials.NewEnvCredentials()), nil
}

sess, err := session.NewSession()
if err != nil {
return nil, err
}

return v4.NewSigner(sess.Config.Credentials), nil
}
4 changes: 3 additions & 1 deletion go.mod
Expand Up @@ -81,7 +81,7 @@ require (
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/goark/errs v1.1.0 // indirect
github.com/goark/errs v1.3.2 // indirect
github.com/goark/go-cvss v1.6.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
Expand All @@ -99,6 +99,7 @@ require (
github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf // indirect
Expand Down Expand Up @@ -167,6 +168,7 @@ require (
github.com/Khan/genqlient v0.6.0
github.com/Masterminds/semver v1.5.0
github.com/arangodb/go-driver v1.6.0
github.com/aws/aws-sdk-go v1.44.284
github.com/fsnotify/fsnotify v1.6.0
github.com/go-git/go-git/v5 v5.8.1
github.com/gobwas/glob v0.2.3
Expand Down
5 changes: 3 additions & 2 deletions go.sum
Expand Up @@ -1320,8 +1320,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goark/errs v1.1.0 h1:FKnyw4LVyRADIjM8Nj0Up6r0/y5cfADvZAd1E+tthXE=
github.com/goark/errs v1.1.0/go.mod h1:TtaPEoadm2mzqzfXdkkfpN2xuniCFm2q4JH+c1qzaqw=
github.com/goark/errs v1.3.2 h1:ifccNe1aK7Xezt4XVYwHUqalmnfhuphnEvh3FshCReQ=
github.com/goark/errs v1.3.2/go.mod h1:ZsQucxaDFVfSB8I99j4bxkDRfNOrlKINwg72QMuRWKw=
github.com/goark/go-cvss v1.6.6 h1:WJFuIWqmAw1Ilb9USv0vuX+nYzOWJp8lIujseJ/y3sU=
github.com/goark/go-cvss v1.6.6/go.mod h1:H3qbfUSUlV7XtA3EwWNunvXz6OySwWHOuO+R6ZPMQPI=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
Expand Down Expand Up @@ -1738,6 +1738,7 @@ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
Expand Down
8 changes: 8 additions & 0 deletions guac.yaml
Expand Up @@ -9,6 +9,14 @@ neo4j-pass: s3cr3t
neo4j-addr: neo4j://localhost:7687
neo4j-realm: neo4j

# Neptune details
# Populate neptune-endpoint, neptune-port and neptune-region with accurate values.
neptune-user: username
neptune-endpoint: localhost
neptune-port: 8182
neptune-region: us-east-1
neptune-realm: neptune

# Nats setup
nats-addr: nats://localhost:4222

Expand Down
6 changes: 6 additions & 0 deletions pkg/cli/store.go
Expand Up @@ -48,6 +48,12 @@ func init() {
set.String("neo4j-pass", "", "neo4j password credential to connect to graph db")
set.String("neo4j-realm", "neo4j", "realm to connect to graph db")

set.String("neptune-endpoint", "localhost", "address to neptune db")
set.Int("neptune-port", 8182, "port used for neptune db connection")
set.String("neptune-region", "us-east-1", "region to connect to neptune db")
set.String("neptune-user", "", "neptune user credential to connect to graph db")
set.String("neptune-realm", "neptune", "realm to connect to graph db")

set.String("arango-addr", "http://localhost:8529", "address to arango db")
set.String("arango-user", "", "arango user to connect to graph db")
set.String("arango-pass", "", "arango password to connect to graph db")
Expand Down

0 comments on commit bc5c042

Please sign in to comment.