From 4d72ba518165c8396fe00b39552e7bac61fec364 Mon Sep 17 00:00:00 2001 From: Pieterjan Spoelders Date: Thu, 2 Dec 2021 11:53:48 +0100 Subject: [PATCH] Provides SSL/TLS support within the API (#46) * #45: Option to enable and configure SSL/TLS * #45 : TLS support * Minor changes to style + note on SSL port --- doc/user_guide/user-guide.md | 48 ++++++++++++++----- pkg/exasol-rest-api/application_properties.go | 6 ++- pkg/exasol-rest-api/application_runner.go | 16 +++++-- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/doc/user_guide/user-guide.md b/doc/user_guide/user-guide.md index 28b4800..3799bf9 100644 --- a/doc/user_guide/user-guide.md +++ b/doc/user_guide/user-guide.md @@ -49,17 +49,20 @@ For the API tokens' value use the following format: `token1,token2,token3,...` #### All Available Properties -| Property | Default | Description | -| :--------------------------: | :-------------: | :--------------------------------------------------- | -| API_TOKENS | | List of allowed API tokens for authorization. | -| SERVER_ADDRESS | "0.0.0.0:8080" | Address for the server to listen for new connection. | -| EXASOL_USER | | Name of the Exasol service account. | -| EXASOL_PASSWORD | | Password of the Exasol service account. | -| EXASOL_HOST | "localhost" | Exasol host. | -| EXASOL_PORT | 8563 | Exasol port. | -| EXASOL_WEBSOCKET_API_VERSION | 2 | Version of Exasol Websocket API. | -| EXASOL_ENCRYPTION | 1 | Automatic [Exasol connection encryption][1]. Use 1 to enable it and -1 to disable. | -| EXASOL_TLS | 1 | TLS/SSL verification. Disable it if you want to use a self-signed or invalid certificate (server side). Use 1 to enable it and -1 to disable. | +| Property | Default | Description | +| :--------------------------- | :------------: | :----------------------------------------------------------- | +| API_TOKENS | | List of allowed API tokens for authorization. | +| SERVER_ADDRESS | "0.0.0.0:8080" | Address for the server to listen for new connection. | +| EXASOL_USER | | Name of the Exasol service account. | +| EXASOL_PASSWORD | | Password of the Exasol service account. | +| EXASOL_HOST | "localhost" | Exasol host. | +| EXASOL_PORT | 8563 | Exasol port. | +| EXASOL_WEBSOCKET_API_VERSION | 2 | Version of Exasol Websocket API. | +| EXASOL_ENCRYPTION | 1 | Automatic [Exasol connection encryption][1]. Use 1 to enable it and -1 to disable. | +| EXASOL_TLS | 1 | Database TLS/SSL verification. Disable it if you want to use a self-signed or invalid certificate (server side). Use 1 to enable it and -1 to disable. | +| API_TLS | false | Enable API TLS/SSL. | +| API_TLS_PKPATH | | Path of the private key file. | +| API_TLS_CERTPATH | | Path of the certificate file. | ### Authorization @@ -100,8 +103,27 @@ The service allows 30 requests per minute for all API endpoints. The limitation ### Using Secured Connection (HTTPS) -We strongly recommend setting up an HTTPS when deploying the API service. -A recommended way is setting up a publicly accessible proxy server that [terminates SSL](https://en.wikipedia.org/wiki/TLS_termination_proxy) and forwards the request to the API service. +We strongly recommend using HTTPS when deploying the API service. + +#### Enable TLS within the API itself + +You can enable HTTPS within the service itself using the `API_TLS` (set it to true to enable TLS), `API_TLS_PKPATH` (path to `private key.pem` file) and `API_TLS_CERTPATH` (path to `certificate.pem` file) configuration properties. + +These entries would look like this in your configuration .yml file: + +> API_TLS: true +> +> API_TLS_PKPATH: "C:\\\tls\\\private.key.pem" +> +> API_TLS_CERTPATH: "C:\\\tls\\\domain.cert.pem" + +You might also want to change the listening port to port 443 (the default for SSL for browsers and many other applications). You can do this by changing the `SERVER_ADDRESS` to "0.0.0.0:443". + +> SERVER_ADDRESS : "0.0.0.0:443" + +#### Using a proxy and SSL termination + +Another way is setting up a publicly accessible proxy server that [terminates SSL](https://en.wikipedia.org/wiki/TLS_termination_proxy) and forwards the request to the API service. Here are a few examples of services you could use: diff --git a/pkg/exasol-rest-api/application_properties.go b/pkg/exasol-rest-api/application_properties.go index 8819fff..9c7ce9b 100644 --- a/pkg/exasol-rest-api/application_properties.go +++ b/pkg/exasol-rest-api/application_properties.go @@ -2,8 +2,9 @@ package exasol_rest_api import ( "fmt" - error_reporting_go "github.com/exasol/error-reporting-go" "os" + + error_reporting_go "github.com/exasol/error-reporting-go" ) const APITokensKey string = "API_TOKENS" @@ -29,6 +30,9 @@ type ApplicationProperties struct { ExasolWebsocketAPIVersion int `yaml:"EXASOL_WEBSOCKET_API_VERSION"` Encryption int `yaml:"EXASOL_ENCRYPTION"` UseTLS int `yaml:"EXASOL_TLS"` + APIUseTLS bool `yaml:"API_TLS"` + APITLSPrivateKeyPath string `yaml:"API_TLS_PKPATH"` + APITLSCertificatePath string `yaml:"API_TLS_CERTPATH"` } // GetApplicationProperties creates an application properties. diff --git a/pkg/exasol-rest-api/application_runner.go b/pkg/exasol-rest-api/application_runner.go index 975fd4d..ef4cc80 100644 --- a/pkg/exasol-rest-api/application_runner.go +++ b/pkg/exasol-rest-api/application_runner.go @@ -1,16 +1,17 @@ package exasol_rest_api import ( - "github.com/exasol/error-reporting-go" + _ "main/doc/swagger" // importing Swagger-generated documentation + "net/http" + "time" + + error_reporting_go "github.com/exasol/error-reporting-go" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" "github.com/ulule/limiter/v3" mgin "github.com/ulule/limiter/v3/drivers/middleware/gin" "github.com/ulule/limiter/v3/drivers/store/memory" - _ "main/doc/swagger" // importing Swagger-generated documentation - "net/http" - "time" ) // Run starts the REST API service. @@ -26,7 +27,12 @@ func Run() { swaggerURL := ginSwagger.URL("/swagger/doc.json") AddEndpoints(router, application) router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, swaggerURL)) - err := router.Run(applicationProperties.ApplicationServer) + var err error + if applicationProperties.APIUseTLS { + err = router.RunTLS(applicationProperties.ApplicationServer, applicationProperties.APITLSCertificatePath, applicationProperties.APITLSPrivateKeyPath) + } else { + err = router.Run(applicationProperties.ApplicationServer) + } if err != nil { panic(error_reporting_go.ExaError("E-ERA-1").Message("error starting API server: {{error}}").