Skip to content

Commit

Permalink
Add mTLS for GraphQL APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
sgayangi committed Mar 13, 2024
1 parent 1d502a0 commit 00970f3
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 9 deletions.
10 changes: 10 additions & 0 deletions adapter/internal/operator/synchronizer/gql_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,20 @@ func generateGQLAdapterInternalAPI(apiState APIState, gqlRoute *GQLRouteState, e
RateLimitPolicies: apiState.RateLimitPolicies,
ResourceRateLimitPolicies: apiState.ResourceRateLimitPolicies,
}

if err := adapterInternalAPI.SetInfoGQLRouteCR(gqlRoute.GQLRouteCombined, resourceParams); err != nil {
loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2631, logging.MAJOR, "Error setting GQLRoute CR info to adapterInternalAPI. %v", err))
return nil, nil, err
}

if apiState.MutualSSL != nil && apiState.MutualSSL.Required != "" && !adapterInternalAPI.GetDisableAuthentications() {
adapterInternalAPI.SetDisableMtls(apiState.MutualSSL.Disabled)
adapterInternalAPI.SetMutualSSL(apiState.MutualSSL.Required)
adapterInternalAPI.SetClientCerts(apiState.APIDefinition.Name, apiState.MutualSSL.ClientCertificates)
} else {
adapterInternalAPI.SetDisableMtls(true)
}

vHosts := getVhostsForGQLAPI(gqlRoute.GQLRouteCombined)
labels := getLabelsForGQLAPI(gqlRoute.GQLRouteCombined)
listeners, relativeSectionNames := getListenersForGQLAPI(gqlRoute.GQLRouteCombined, adapterInternalAPI.UUID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ public String init(Api api) {
String version = api.getVersion();
String apiType = api.getApiType();
List<ResourceConfig> resources = new ArrayList<>();
Map<String, String> mtlsCertificateTiers = new HashMap<>();
String mutualSSL = api.getMutualSSL();
boolean applicationSecurity = api.getApplicationSecurity();

Expand Down Expand Up @@ -145,7 +144,7 @@ public String init(Api api) {
.resources(resources).apiType(apiType).apiLifeCycleState(apiLifeCycleState).tier(api.getTier())
.envType(api.getEnvType()).disableAuthentication(api.getDisableAuthentications())
.disableScopes(api.getDisableScopes()).trustStore(trustStore).organizationId(api.getOrganizationId())
.mutualSSL(mutualSSL)
.mutualSSL(mutualSSL).transportSecurity(api.getTransportSecurity())
.applicationSecurity(applicationSecurity).jwtConfigurationDto(jwtConfigurationDto)
.apiDefinition(apiDefinition).environment(api.getEnvironment())
.subscriptionValidation(api.getSubscriptionValidation()).graphQLSchemaDTO(graphQLSchemaDTO).build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
name: "GraphQL API"
basePath: "/graphql"
version: "3.14"
type: "GRAPHQL"
id: "graphql-auth-disabled"
defaultVersion: false
subscriptionValidation: false
endpointConfigurations:
production:
endpoint: "http://graphql-faker-service:9002/graphql"
operations:
- target: "hero"
verb: "QUERY"
secured: true
scopes: []
- target: "reviews"
verb: "QUERY"
secured: true
scopes: []
- target: "search"
verb: "QUERY"
secured: true
scopes: []
- target: "character"
verb: "QUERY"
secured: true
scopes: []
- target: "droid"
verb: "QUERY"
secured: true
scopes: []
- target: "human"
verb: "QUERY"
secured: true
scopes: []
- target: "allHumans"
verb: "QUERY"
secured: true
scopes: []
authentication:
- authType: OAuth2
required: mandatory
enabled: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: "GraphQL API"
basePath: "/graphql"
version: "3.14"
type: "GRAPHQL"
id: "graphql-mtls"
defaultVersion: false
subscriptionValidation: false
endpointConfigurations:
production:
endpoint: "http://graphql-faker-service:9002/graphql"
operations:
- target: "hero"
verb: "QUERY"
secured: true
scopes: []
- target: "reviews"
verb: "QUERY"
secured: true
scopes: []
- target: "search"
verb: "QUERY"
secured: true
scopes: []
- target: "character"
verb: "QUERY"
secured: true
scopes: []
- target: "droid"
verb: "QUERY"
secured: true
scopes: []
- target: "human"
verb: "QUERY"
secured: true
scopes: []
- target: "allHumans"
verb: "QUERY"
secured: true
scopes: []
authentication:
- authType: OAuth2
required: mandatory
enabled: true
- authType: mTLS
enabled: true
required: mandatory
certificates:
- name: mtls-test-configmap
key: tls.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: "GraphQL API"
basePath: "/graphql"
version: "3.14"
type: "GRAPHQL"
id: "graphql-mtls-optional"
defaultVersion: false
subscriptionValidation: false
endpointConfigurations:
production:
endpoint: "http://graphql-faker-service:9002/graphql"
operations:
- target: "hero"
verb: "QUERY"
secured: true
scopes: []
- target: "reviews"
verb: "QUERY"
secured: true
scopes: []
- target: "search"
verb: "QUERY"
secured: true
scopes: []
- target: "character"
verb: "QUERY"
secured: true
scopes: []
- target: "droid"
verb: "QUERY"
secured: true
scopes: []
- target: "human"
verb: "QUERY"
secured: true
scopes: []
- target: "allHumans"
verb: "QUERY"
secured: true
scopes: []
authentication:
- authType: OAuth2
required: mandatory
enabled: true
- authType: mTLS
enabled: true
required: mandatory
certificates:
- name: mtls-test-configmap
key: tls.crt
110 changes: 103 additions & 7 deletions test/cucumber-tests/src/test/resources/tests/api/GraphQL.feature
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,107 @@ Feature: Generating APK conf for GraphQL API
| 429 |
| 500 |

Scenario: Undeploy API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "graphql-without-sub"
Then the response status code should be 202

Scenario: Deploying APK conf using a valid GraphQL API definition with mTLS mandatory and valid certificate
Given The system is ready
And I have a valid token with a client certificate "config-map-1.txt"
When I use the APK Conf file "artifacts/apk-confs/graphql/graphql_with_mtls.apk-conf"
And the definition file "artifacts/definitions/graphql_sample_api.graphql"
And make the API deployment request
Then the response status code should be 200
Then I set headers
| Authorization | bearer ${accessToken} |
| X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
And I send "POST" request to "https://default.gw.wso2.com:9095/graphql/3.14" with body "{\"query\":\"{ allHumans { name } }\"}"
And I eventually receive 200 response code, not accepting
| 429 |
| 500 |

Scenario: Undeploy API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "graphql-mtls"
Then the response status code should be 202

Scenario: Deploying APK conf using a valid GraphQL API definition with mTLS mandatory and no certificate
Given The system is ready
And I have a valid subscription
When I use the APK Conf file "artifacts/apk-confs/graphql/graphql_with_mtls.apk-conf"
And the definition file "artifacts/definitions/graphql_sample_api.graphql"
And make the API deployment request
Then the response status code should be 200
Then I set headers
| Authorization | bearer ${accessToken} |
And I send "POST" request to "https://default.gw.wso2.com:9095/graphql/3.14" with body "{\"query\":\"{ allHumans { name } }\"}"
And I eventually receive 401 response code, not accepting
| 200 |
| 429 |
| 500 |

Scenario: Undeploy API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "graphql-mtls"
Then the response status code should be 202

Scenario: Deploying APK conf using a valid GraphQL API definition with OAuth2 mandatory mTLS optional
Given The system is ready
And I have a valid token with a client certificate "config-map-1.txt"
When I use the APK Conf file "artifacts/apk-confs/graphql/graphql_with_mtls_optional_oauth2_mandatory.apk-conf"
And the definition file "artifacts/definitions/graphql_sample_api.graphql"
And make the API deployment request
Then the response status code should be 200
Then I set headers
| Authorization | bearer ${accessToken} |
| X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
And I send "POST" request to "https://default.gw.wso2.com:9095/graphql/3.14" with body "{\"query\":\"{ allHumans { name } }\"}"
And I eventually receive 200 response code, not accepting
| 429 |
| 500 |
Then I set headers
| Authorization | bearer ${accessToken} |
And I send "POST" request to "https://default.gw.wso2.com:9095/graphql/3.14" with body "{\"query\":\"{ allHumans { name } }\"}"
And I eventually receive 200 response code, not accepting
| 429 |
| 500 |
And I have a valid token with a client certificate "invalid-cert.txt"
Then I set headers
| Authorization | bearer ${accessToken} |
| X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
And I send "POST" request to "https://default.gw.wso2.com:9095/graphql/3.14" with body "{\"query\":\"{ allHumans { name } }\"}"
And I eventually receive 401 response code, not accepting
| 429 |
| 500 |

Scenario: Undeploy API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "graphql-mtls-optional"
Then the response status code should be 202

Scenario: Deploying GraphQL API with OAuth2 disabled
Given The system is ready
And I have a valid subscription
When I use the APK Conf file "artifacts/apk-confs/graphql/graphql_with_disabled_auth.apk-conf"
And the definition file "artifacts/definitions/graphql_sample_api.graphql"
And make the API deployment request
Then the response status code should be 200
And I send "POST" request to "https://default.gw.wso2.com:9095/graphql/3.14" with body "{\"query\":\"{ allHumans { name } }\"}"
And I eventually receive 200 response code, not accepting
| 429 |
| 500 |

Scenario: Undeploy API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "graphql-auth-disabled"
Then the response status code should be 202

Scenario: Deploying APK conf using a valid GraphQL API definition containing a subscription resource
Given The system is ready
And I have a valid subscription
Expand All @@ -36,10 +137,5 @@ Feature: Generating APK conf for GraphQL API
Scenario Outline: Undeploy API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "<apiID>"
Then the response status code should be <expectedStatusCode>

Examples:
| apiID | expectedStatusCode |
| graphql-with-sub | 202 |
| graphql-without-sub | 202 |
When I undeploy the API whose ID is "graphql-with-sub"
Then the response status code should be 202

0 comments on commit 00970f3

Please sign in to comment.