diff --git a/rest/tls/README.md b/rest/tls/README.md index eb7c6b4..33e714c 100644 --- a/rest/tls/README.md +++ b/rest/tls/README.md @@ -7,8 +7,10 @@ For more information on using TLS in your REST apis and other services [see our This examples demonstrates a number of API Connect for GraphQL capabilities: - Use of `@rest(tls:)` +- Use of schema level `@rest` - stepzen service - Simple ecmascript capability for reshaping data. +- config.yaml usage for `@rest` using process for clean CI/CD ## mTLS and certificates @@ -22,18 +24,48 @@ When the tls entry is given the name of a configuration entry, you can provide - `key` - the client certifcate key The data should be in PEM format. -In our examples, we have two configuration: `selfsign` with a `ca` entry and `selfsignedmtls` with all three entries. +In our examples, we have two configuration: `myserver`(with a +selfsigned cert) with a `ca` entry and `mymtlsserver` requiring +mtls)with all three entries. + +The same configuration entry is used +for both tls and server configuration, so you'll see +`@rest(tls:"myserver" configuration:"myserver")`. + +If the tls `ca` was a shared private `ca`, you'd want to have a common +`tls` config entry for all servers so you'd probably put them into two +different configuration entries TLS 1.2 and 1.3 are supported. TLS 1.0 and 1.1 are not supported. +### Schema `@rest` + +You can definte a common `@rest(name:)` profile as a schema level definition to be shared as `@rest(use:)`. + +This allows for common configuraiton to be creatd and shared. + +``` +schema +... + @rest(name: "commonserver", endpoint: "$url;", tls: "myserver" configuration: "myserver") { + query: Query +} +``` +create a `commonserver` profile with endpoint, tls, and configuration. + +When `@rest(use:"commonserver")` is encountered, those arguments will be applied. + +Since there is only a single `@rest` definition, this is a contrivied example, but the utility should be clear especially for CI/CD. + + ## Try it out! -`rest_self` in tls.graphql provides an example of self signed certificates by pointing to the `selfsign` resource in config.yaml. That configuration contains `ca: STEPZEN_SERVER_CRT` +`rest_self` in tls.graphql provides an example of self signed certificates by pointing to the `myserver` resource in config.yaml. That configuration contains `ca: STEPZEN_SERVER_CRT` During `stepzen deploy`, the `STEPZEN_SERVER_CRT` environment variable is expanded and the result will be a yaml that looks like: ``` configurationset: - configuration: - name: selfsign + name: myserver ca: | -----BEGIN CERTIFICATE----- MIIF5zCCA8+gAwIBAgIUS2BwtghuA7PREQ5AWzOeeT+tCe4wDQYJKoZIhvcNAQEL @@ -41,7 +73,7 @@ configurationset: -----END CERTIFICATE----- ``` -The `selfsignedmtls` configuration contains an example mutual TLS configuration. +The `mymtlsserver` configuration contains an example mutual TLS configuration. Two safe approaches are to set the environment variables from secrets or to have a `.env` file. @@ -88,6 +120,14 @@ By default, `rest_self` uses `host.docker.internal` which works in most modern For Podman, you may need to change this to `host.containers.internal` or `localhost` depending on your podman defaults. You may also need to modify your podman default configuration to allow for such access. +We apply a layer of indirection for the endpoint. The actual value is held in the configuation as `url` and that is actually obtained from the environment variable `STEPZEN_SERVER_URL`. This allows for CI/CD process to inject the root URL by setting the env variable. + +Here, this can be done by running, replacing the `SERVER_URL` with the value appropriate to your container runtime toolset. +``` +(cd tests; make env SERVER_URL="http://localhost:8443") +``` +This won't overwrite an existing .env, so remove it if already exists. + ### env variables You can set `STEPZEN_*` env variables in .env or using export. @@ -136,11 +176,16 @@ that it is as you expected. You are looking for something that looks like: ``` -"configuration":{"configurationset":[{"configuration":{"name":"selfsign","ca": +"configuration":{"configurationset":[{"configuration":{"name":"myserver","ca": "-----BEGIN CERTIFICATE-----\nMIIF5zCCA8+gAwIBAgIUS2BwtghuA7PREQ5AWzOeeT+tCe4wDQYJKoZIhvcNAQEL\nBQAwbTE... ``` notice the '\n'. If you see spaces you've done something wrong upsteram. +### Reserved environment variables + +`STEPZEN_SERVER_URL` is used by the stepzen cli to identify the API Connect for GraphQL server and should be avoided to prevent stepzen cli issues. + +Here's a full list of stepzen cli special variables you should avoid using. ### Debugging You can debug using stepzen request by adding `-H "stepzen-debug-level: 1"` diff --git a/rest/tls/config.yaml b/rest/tls/config.yaml index 6f09e5c..cf2acb5 100644 --- a/rest/tls/config.yaml +++ b/rest/tls/config.yaml @@ -1,9 +1,13 @@ +# provide values through environment variables to mimimize secret exposure and +# adhere to clean ci/cd process. env variables/secrets should be injected configurationset: - configuration: - name: selfsign + name: myserver ca: STEPZEN_SERVER_CRT + url: STEPZEN_SERVICE_URL - configuration: - name: selfsignedmtls + name: mymtlsserver ca: STEPZEN_SERVER_CRT cert: STEPZEN_CLIENT_CRT key: STEPZEN_CLIENT_KEY + url: STEPZEN_SERVICE_URL diff --git a/rest/tls/index.graphql b/rest/tls/index.graphql index 233a241..e8dc67f 100644 --- a/rest/tls/index.graphql +++ b/rest/tls/index.graphql @@ -1,3 +1,5 @@ -schema @sdl(files: ["tls.graphql"]) { +schema + @sdl(files: ["tls.graphql"]) + @rest(name: "commonserver", endpoint: "$url;", tls: "myserver" configuration: "myserver") { query: Query } diff --git a/rest/tls/tests/Makefile b/rest/tls/tests/Makefile index fd513a1..cf50745 100644 --- a/rest/tls/tests/Makefile +++ b/rest/tls/tests/Makefile @@ -1,5 +1,11 @@ # Makefile to build and validate a pair of *example* self-signed certificates for *simple* tests +# alternate endpoint settings for different container toolsets +# hostname: "https://host.docker.internal:8443" +# hostname: "https://localhost:8443" +# hostname: "https://host.rancher-desktop.internal:8443" +SERVER_URL:=https://host.docker.internal:8443 + # enable to debug ssl server # DEBUG:=-debug all: client.crt server.crt env @@ -27,6 +33,7 @@ clean: env: ../.env ../.env: client.crt server.crt - ( echo STEPZEN_CLIENT_CRT=\""`cat client.crt`"\"; \ + ( echo STEPZEN_SERVICE_URL=\"$(SERVER_URL)\"; \ + echo STEPZEN_CLIENT_CRT=\""`cat client.crt`"\"; \ echo STEPZEN_CLIENT_KEY=\""`cat client.key`"\"; \ echo STEPZEN_SERVER_CRT=\""`cat server.crt`"\") > ../.env diff --git a/rest/tls/tls.graphql b/rest/tls/tls.graphql index 3a84243..f7007cb 100644 --- a/rest/tls/tls.graphql +++ b/rest/tls/tls.graphql @@ -1,15 +1,18 @@ type Query { """ + typically, there will be a common set of server configurations that are shared among many + different `@rest` calls, so we actually specify the `@rest(tls:)` in a schema level + `@rest` definition called `commonserver` in index.graphql + + `@rest(use:"commonserver")` picks up the `@rest(tls:)` and the `@rest(endpoint:)` + will contact localhost using host.docker.internal and 8443 and selfsign configuration the ecmascript is used to repackage any content coming back (openssl s_server returns html) """ rest_self: JSON @rest( - endpoint: "https://host.docker.internal:8443/" - # alternate endpoint settings for different container toolsets - # endpoint: "https://localhost:8443/" - # endpoint: "https://host.rancher-desktop.internal:8443/" - tls: "selfsign" + use: "commonserver" + path: "/path" ecmascript: """ function transformREST(s) { return JSON.stringify(