Skip to content

Commit

Permalink
THREESCALE-11156 add Database TLS doc
Browse files Browse the repository at this point in the history
  • Loading branch information
austincunningham committed Jan 14, 2025
1 parent a2b55f2 commit 8c46579
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 11 deletions.
15 changes: 15 additions & 0 deletions doc/apimanager-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,11 @@ For Mysql:
| URL | URL of the Porta database. Format: `mysql2://<AdminUser>:<AdminPassword>@<DatabaseHost>/<DatabaseName>`, where `<AdminUser>` must be an already existing user in the external database with full permissions on the specified `<DatabaseName>` logical database and `<DatabaseName>` must be an already existing logical database in the external database.| Mandatory when the instance is managed externally. A default is only set when database is managed internally.<br/>When managed internally:<br/>`mysql2://root:<AutogeneratedValue>@system-mysql/mysql`.|
| DB_USER | Not used by 3scale components. Only used when the database is managed internally to create a new user granted with superuser permissions for the database specified in the `URL` field. | `mysql` |
| DB_PASSWORD | Not used by 3scale components. Only used when the database is managed internally to create a new user granted with superuser permissions for the database specified in the `URL` field. | Autogenerated value |
| DATABASE_SSL_MODE | [Database SSL Mode](https://github.com/brianmario/mysql2?tab=readme-ov-file#ssltls-options) | Required to set TLS Database connection. Only for TLS |
| DB_SSL_CA | SSL CA certificate | Required to set TLS Database connection. Only for TLS |
| DB_SSL_CERT | SSL CERT certificate | Required to set TLS Database connection. Only for TLS |
DB_SSL_KEY | SSL Key | Required to set TLS Database connection. Only for TLS |


For Postgresql:

Expand All @@ -746,6 +751,11 @@ For Postgresql:
| URL | URL of the Porta database. Format: `postgresql://<AdminUser>:<AdminPassword>@<DatabaseHost>/<DatabaseName>`, where `<AdminUser>` must be an already existing user in the external database with full permissions on the specified `<DatabaseName>` logical database and `<DatabaseName>` must be an already existing logical database in the external database.| Mandatory when the instance is managed externally. A default is only set when database is managed internally.<br/>When managed internally:<br/>`postgresql://system:<AutoGeneratedValue>@system-postgresql/system`.|
| DB_USER | Not used by 3scale components. Only used when the database is managed internally to create a user with superuser power. | `system` |
| DB_PASSWORD | Not used by 3scale components. Only used when the database is managed internally to create a user with superuser power. | Autogenerated value |
| DATABASE_SSL_MODE | [Database SSL Mode](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) | Required to set TLS Database connection. Only for TLS |
| DB_SSL_CA | SSL CA certificate | Required to set TLS Database connection. Only for TLS |
| DB_SSL_CERT | SSL CERT certificate | Required to set TLS Database connection. Only for TLS |
DB_SSL_KEY | SSL Key | Required to set TLS Database connection. Only for TLS |


For Oracle:

Expand Down Expand Up @@ -812,6 +822,11 @@ For Oracle:
| ZYNC_DATABASE_PASSWORD | Database password associated to the user specified in the `DATABASE_URL` parameter | When the database is managed externally, this parameter is mandatory and must have the same value as the password part of the `DATABASE_URL` parameter in this secret. Otherwise the default value is an autogenerated value if not defined |
| SECRET_KEY_BASE | Zync's application key generator to encrypt communications | Autogenerated value |
| ZYNC_AUTHENTICATION_TOKEN | Authentication token used to authenticate System when calling Zync | Autogenerated value |
| DATABASE_SSL_MODE | [Database SSL Mode](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) | Required to set TLS Database connection. Only for TLS |
| DB_SSL_CA | SSL CA certificate | Required to set TLS Database connection. Only for TLS |
| DB_SSL_CERT | SSL CERT certificate | Required to set TLS Database connection. Only for TLS |
DB_SSL_KEY | SSL Key | Required to set TLS Database connection. Only for TLS |


### fileStorage-S3-credentials-secret

Expand Down
42 changes: 42 additions & 0 deletions doc/operator-user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,48 @@ Secret name must be `zync`.

See [Zync secret](apimanager-reference.md#zync) for reference.

#### TLS database configuration ####

It is possible to connect to both the system-database and zync database via TLS provided these databases have TLS enabled. To enable TLS communication to these databases you will need to configure the ApiManager and the database secret.

In ApiManager CR we set the boolean to enable TLS configuration for the respictive databases
- `spec.zyncDatabaseTLSEnabled: true`
- `spec.systemDatabaseTLSEnabled: true`

We pass the cert files in via the respective secret i.e. system-database & zync

You set the following values in the secret to connect to the database via TLS

| Secret Key | Secret Value |
| --- | --- |
| DATABASE_SSL_MODE | string of the SSL mode for database connection |
| DB_SSL_CA | actual ca cert |
| DB_SSL_CERT | actual client cert |
| DB_SSL_KEY | actual client key |

e.g. for system-database
```bash
oc create secret generic system-database \
--from-literal=DATABASE_SSL_MODE=verify-ca \
--from-literal=DATABASE_URL=postgresql://postgres:[email protected]/zync_production \
--from-literal=ZYNC_DATABASE_PASSWORD=password \
--from-file=DB_SSL_CA=rootCA.crt \
--from-file=DB_SSL_CERT=client.crt \
--from-file=DB_SSL_KEY=client.key
```
e.g. for zync
```bash
oc create secret generic zync \
--from-literal=DATABASE_SSL_MODE=verify-ca \
--from-literal=DATABASE_URL=postgresql://postgres:[email protected]/zync_production \
--from-literal=ZYNC_DATABASE_PASSWORD=password \
--from-file=DB_SSL_CA=rootCA.crt \
--from-file=DB_SSL_CERT=client.crt \
--from-file=DB_SSL_KEY=client.key
```

Once these values have been set and are correct the operator will proceed to mount the certs into the related pods to enable client TLS communication.

#### S3 Filestorage Installation
3scale’s FileStorage being in a S3 service instead of in a PVC.

Expand Down
30 changes: 30 additions & 0 deletions pkg/3scale/amp/component/zync.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,36 @@ func NewZync(options *ZyncOptions) *Zync {
}

func (zync *Zync) Secret() *v1.Secret {
secret := &v1.Secret{}
if secret.Labels == nil {
secret.Labels = make(map[string]string)
}
labels := secret.Labels
labels["apimanager.apps.3scale.net/watched-by"] = "zync"

if zync.Options.ZyncDbTLSEnabled {
return &v1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: ZyncSecretName,
Labels: labels,
},
StringData: map[string]string{
ZyncSecretKeyBaseFieldName: zync.Options.SecretKeyBase,
ZyncSecretDatabaseURLFieldName: zync.Options.DatabaseURL,
ZyncSecretDatabasePasswordFieldName: zync.Options.DatabasePassword,
ZyncSecretAuthenticationTokenFieldName: zync.Options.AuthenticationToken,
ZyncSecretDatabaseSslMode: zync.Options.DatabaseSslMode,
ZyncSecretSslCa: zync.Options.DatabaseSslCa,
ZyncSecretSslCert: zync.Options.DatabaseSslCert,
ZyncSecretSslKey: zync.Options.DatabaseSslKey,
},
Type: v1.SecretTypeOpaque,
}
}
return &v1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Expand Down
8 changes: 0 additions & 8 deletions pkg/3scale/amp/operator/zync_options_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ func (z *ZyncOptionsProvider) GetZyncOptions() (*component.ZyncOptions, error) {
z.setTopologySpreadConstraints()

z.zyncOptions.CommonLabels = z.commonLabels()
if z.apimanager.IsZyncDatabaseTLSEnabled() {
z.zyncOptions.CommonZyncSecretLabels = z.commonZyncSecretLabels()
}
z.zyncOptions.CommonZyncLabels = z.commonZyncLabels()
z.zyncOptions.CommonZyncQueLabels = z.commonZyncQueLabels()
z.zyncOptions.CommonZyncDatabaseLabels = z.commonZyncDatabaseLabels()
Expand Down Expand Up @@ -245,11 +242,6 @@ func (z *ZyncOptionsProvider) commonLabels() map[string]string {
"threescale_component": "zync",
}
}
func (z *ZyncOptionsProvider) commonZyncSecretLabels() map[string]string {
labels := z.commonLabels()
labels["apimanager.apps.3scale.net/watched-by"] = "zync"
return labels
}

func (z *ZyncOptionsProvider) commonZyncLabels() map[string]string {
labels := z.commonLabels()
Expand Down
16 changes: 13 additions & 3 deletions pkg/helper/envvarutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package helper

import (
"context"
"fmt"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"reflect"
Expand Down Expand Up @@ -164,8 +165,16 @@ func EnvVarReconciler(desired []v1.EnvVar, existing *[]v1.EnvVar, envVar string)
// check if the secret ssl certs are populated and sets the path if they are
// system-app and zync use this function
func TlsCertPresent(pathSslEnvVar string, secretName string, databaseTLSEnabled bool) string {
cfg, _ := config.GetConfig()
client, _ := client.New(cfg, client.Options{})
cfg, err := config.GetConfig()
if err != nil {
fmt.Printf("clientTLS error, get config : %v", err)
return ""
}
clientTLS, err := client.New(cfg, client.Options{})
if err != nil {
fmt.Printf("clientTLS error, client create : %v", err)
return ""
}
namespace, _ := GetOperatorNamespace()
var path string
var sslEnvVar string
Expand All @@ -191,8 +200,9 @@ func TlsCertPresent(pathSslEnvVar string, secretName string, databaseTLSEnabled
Name: secretName,
Namespace: namespace,
}
err := client.Get(context.TODO(), nn, &secret)
err = clientTLS.Get(context.TODO(), nn, &secret)
if err != nil {
fmt.Printf("clientTLS error, get secret : %v", err)
return ""
}

Expand Down
7 changes: 7 additions & 0 deletions pkg/reconcilers/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,13 @@ func DeploymentPodInitContainerImageMutator(desired, existing *k8sappsv1.Deploym
updated := false

for i, desiredContainer := range desired.Spec.Template.Spec.InitContainers {
if i >= len(existing.Spec.Template.Spec.InitContainers) {
// Add missing containers from desired to existing
existing.Spec.Template.Spec.InitContainers = append(existing.Spec.Template.Spec.InitContainers, desiredContainer)
fmt.Printf("Added missing container: %s\n", desiredContainer.Name)
updated = true
continue
}
existingContainer := &existing.Spec.Template.Spec.InitContainers[i]

if !reflect.DeepEqual(existingContainer.Image, desiredContainer.Image) {
Expand Down

0 comments on commit 8c46579

Please sign in to comment.