Skip to content

Commit

Permalink
feat(GraphQL): Add introspection headers to custom logic (#5775) (#5858)
Browse files Browse the repository at this point in the history
Fixes GRAPHQL-510
This PR introduces `introspectionHeaders` for custom logic in GraphQL which will only be used for making the introspection query to the remote endpoint. Also `forwardHeaders` and `secretHeaders` cannot overlap.

(cherry picked from commit cf5df22)
  • Loading branch information
vardhanapoorv authored Jul 7, 2020
1 parent e7e84c7 commit c8019d6
Show file tree
Hide file tree
Showing 39 changed files with 199 additions and 45 deletions.
11 changes: 6 additions & 5 deletions graphql/e2e/custom_logic/custom_logic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func TestCustomQueryShouldForwardHeaders(t *testing.T) {
url: "http://mock:8888/verifyHeaders",
method: "GET",
forwardHeaders: ["X-App-Token", "X-User-Id"],
secretHeaders: ["Github-Api-Token", "X-App-Token"]
secretHeaders: ["Github-Api-Token"]
})
}
Expand Down Expand Up @@ -204,12 +204,12 @@ func TestCustomNameForwardHeaders(t *testing.T) {
url: "http://mock:8888/verifyCustomNameHeaders",
method: "GET",
forwardHeaders: ["X-App-Token:App", "X-User-Id"],
secretHeaders: ["Authorization:Github-Api-Token", "X-App-Token"]
secretHeaders: ["Authorization:Github-Api-Token"]
introspectionHeaders: ["API:Github-Api-Token"]
})
}
# Dgraph.Secret Github-Api-Token "random-fake-token"
# Dgraph.Secret X-App-Token "should-be-overriden"
`
updateSchemaRequireNoGQLErrors(t, schema)
time.Sleep(2 * time.Second)
Expand Down Expand Up @@ -254,8 +254,9 @@ func TestSchemaIntrospectionForCustomQueryShouldForwardHeaders(t *testing.T) {
http: {
url: "http://mock:8888/validatesecrettoken"
method: "POST"
secretHeaders: ["GITHUB-API-TOKEN"]
graphql: "query($yo: CountryInput!) {countries(filter: $yo)}"
forwardHeaders: ["Content-Type"]
introspectionHeaders: ["GITHUB-API-TOKEN"]
graphql: "query($yo: CountryInput!) {countries(filter: $yo)}"
}
)
}
Expand Down
1 change: 1 addition & 0 deletions graphql/schema/gqlschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}
Expand Down
116 changes: 78 additions & 38 deletions graphql/schema/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -1599,40 +1599,82 @@ func customDirectiveValidation(sch *ast.Schema,

// 12. Finally validate the given graphql operation on remote server, when all locally doable
// validations have finished
si := httpArg.Value.Children.ForName("skipIntrospection")
var skip bool
if si != nil {
skip, err = strconv.ParseBool(si.Raw)
if err != nil {
errs = append(errs, gqlerror.ErrorPosf(graphql.Position,
"Type %s; Field %s; skipIntrospection in @custom directive can only be "+
"true/false, found: `%s`.",
typ.Name, field.Name, si.Raw))
iHeaders := make(map[string]string)
if body != nil || graphql != nil {
var errPos *ast.Position
switch {
case body != nil:
errPos = body.Position
case graphql != nil:
errPos = graphql.Position
default:
// this case is not possible, as requiredFields will have non-0 length only if there was
// some body or graphql. Written only to satisfy logic flow, so that errPos is always
// non-nil.
errPos = dir.Position
}
si := httpArg.Value.Children.ForName("skipIntrospection")
if si != nil {
skip, err = strconv.ParseBool(si.Raw)
if err != nil {
errs = append(errs, gqlerror.ErrorPosf(errPos,
"Type %s; Field %s; skipIntrospection in @custom directive can only be "+
"true/false, found: `%s`.",
typ.Name, field.Name, si.Raw))
}
}
}

forwardHeaders := httpArg.Value.Children.ForName("forwardHeaders")
if forwardHeaders != nil {
for _, h := range forwardHeaders.Children {
key := strings.Split(h.Value.Raw, ":")
if len(key) > 2 {
return append(errs, gqlerror.ErrorPosf(graphql.Position,
"Type %s; Field %s; forwardHeaders in @custom directive should be of the form 'remote_headername:local_headername' or just 'headername'"+
", found: `%s`.",
typ.Name, field.Name, h.Value.Raw))
forwardHeaders := httpArg.Value.Children.ForName("forwardHeaders")
fHeaders := make(map[string]bool)
if forwardHeaders != nil {
for _, h := range forwardHeaders.Children {
key := strings.Split(h.Value.Raw, ":")
if len(key) > 2 {
return append(errs, gqlerror.ErrorPosf(errPos,
"Type %s; Field %s; forwardHeaders in @custom directive should be of the form 'remote_headername:local_headername' or just 'headername'"+
", found: `%s`.",
typ.Name, field.Name, h.Value.Raw))
}
fHeaders[key[0]] = true
}
}
}

secretHeaders := httpArg.Value.Children.ForName("secretHeaders")
if secretHeaders != nil {
for _, h := range secretHeaders.Children {
key := strings.Split(h.Value.Raw, ":")
if len(key) > 2 {
return append(errs, gqlerror.ErrorPosf(graphql.Position,
"Type %s; Field %s; secretHeaders in @custom directive should be of the form 'remote_headername:local_headername' or just 'headername'"+
", found: `%s`.",
typ.Name, field.Name, h.Value.Raw))
secretHeaders := httpArg.Value.Children.ForName("secretHeaders")
if secretHeaders != nil {
for _, h := range secretHeaders.Children {
secretKey := strings.Split(h.Value.Raw, ":")
if len(secretKey) > 2 {
return append(errs, gqlerror.ErrorPosf(errPos,
"Type %s; Field %s; secretHeaders in @custom directive should be of the form 'remote_headername:local_headername' or just 'headername'"+
", found: `%s`.",
typ.Name, field.Name, h.Value.Raw))
}
if fHeaders != nil {
if fHeaders[secretKey[0]] {
return append(errs, gqlerror.ErrorPosf(errPos,
"Type %s; Field %s; secretHeaders and forwardHeaders in @custom directive cannot have overlapping headers"+
", found: `%s`.",
typ.Name, field.Name, h.Value.Raw))
}
}
}
}

introspectionHeaders := httpArg.Value.Children.ForName("introspectionHeaders")
if introspectionHeaders != nil {
for _, h := range introspectionHeaders.Children {
key := strings.Split(h.Value.Raw, ":")
if len(key) == 1 {
key = []string{h.Value.Raw, h.Value.Raw}
}
if len(key) > 2 {
return append(errs, gqlerror.ErrorPosf(errPos,
"Type %s; Field %s; introspectionHeaders in @custom directive should be of the form 'remote_headername:local_headername' or just 'headername'"+
", found: `%s`.",
typ.Name, field.Name, h.Value.Raw))
}
iHeaders[key[0]] = key[1]
}
}
}
Expand All @@ -1642,18 +1684,16 @@ func customDirectiveValidation(sch *ast.Schema,
}

if graphql != nil && !skip && graphqlOpDef != nil {
secretHeaders := httpArg.Value.Children.ForName("secretHeaders")
headers := http.Header{}
if secretHeaders != nil {
for _, h := range secretHeaders.Children {
key := strings.Split(h.Value.Raw, ":")
if len(key) == 1 {
key = []string{h.Value.Raw, h.Value.Raw}
}
// We try and fetch the value from the stored secrets.
val := secrets[key[1]]
headers.Add(key[0], string(val))
for key, val := range iHeaders {
// We try and fetch the value from the stored secrets.
value, ok := secrets[val]
if !ok {
return append(errs, gqlerror.ErrorPosf(graphql.Position,
"Type %s; Field %s; introspectionHeaders in @custom directive should use secrets to store the header value. To do that specify `%s` in this format '#Dgraph.Secret name value' at the bottom of your schema file.",
typ.Name, field.Name, val,))
}
headers.Add(key, string(value))
}
if err := validateRemoteGraphql(&remoteGraphqlMetadata{
parentType: typ,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ input CustomHTTP {
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

Expand Down
Loading

0 comments on commit c8019d6

Please sign in to comment.