Enabling the module
The module runs in one of two editions, determined by whether a license key is present in ModuleConfig. Choose the edition before enabling the module.
Base Stronghold: no license key is required; simply enable the module:
d8 system module enable strongholdStronghold EE: create a ModuleConfig with the license key in the spec.settings.license parameter. No separate enable command is needed: the module is enabled by spec.enabled: true in the manifest.
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: stronghold
spec:
enabled: true
version: 1
settings:
license: <STRONGHOLD_EE_LICENSE_KEY>Stronghold EE is licensed separately and is available only in commercial Deckhouse Platform editions. For a comparison of editions, see Editions.
If the module is already running and the storage contains data, add the key by following the instructions for switching to Stronghold EE.
Enabling and initial configuration are covered in more detail in the free “Deckhouse Stronghold capabilities overview” course by Deckhouse Academy (in Russian).
By default, the module starts in the Automatic mode (management.mode) with the Ingress inlet (inlet).
The following modes and inlets are available:
management.mode:Automatic(default) orManual.inlet:Ingress(default),GatewayAPI,LoadBalancer,NodePort, orNone. ForLoadBalancer,NodePort, andNone, you must sethttps.mode: CustomCertificate.
Disabling the module
To disable the module, run the following command:
d8 k annotate mc stronghold modules.deckhouse.io/allow-disabling=true
d8 system module disable strongholdThe module requires confirmation to be disabled, so the modules.deckhouse.io/allow-disabling=true annotation must be set first.
When the module is disabled, all Stronghold containers are deleted from the d8-stronghold namespace, as well as the stronghold-keys secret with the root and unseal keys. If storageClass is not set, the service data is not deleted from the node (see below); if storageClass is set, the data is stored in the data-stronghold-N PVCs, which are deleted together with the StatefulSet. You can enable the module again and put a saved copy of the stronghold-keys secret into the d8-stronghold namespace; access to the data will then be restored.
If storageClass is not set and you no longer need the old data, delete the /var/lib/deckhouse/stronghold directory
from all nodes where Stronghold data is stored (master nodes by default) beforehand.
If storageClass is set, the data resides in the data-stronghold-N PVCs rather than in this directory.
Accessing the service
The service is accessed via inlets. An inlet is a source of input data for a pod. The following inlets are supported: Ingress (default), GatewayAPI, LoadBalancer, NodePort, and None. The examples below use Ingress.
The address of the Stronghold web interface is formed as follows: in the publicDomainTemplate template of the global Deckhouse configuration parameter, the %s key is replaced with stronghold.
For example, if publicDomainTemplate is set to %s-kube.mycompany.tld, the Stronghold web interface is available at stronghold-kube.mycompany.tld.
Using the data storage. Operating modes
The information stored in Stronghold is protected by encryption. To decrypt the storage data, an encryption key is required. This key is also stored together with the data (in the keyring), but it is encrypted with another key called the root key.
To decrypt the data, Stronghold first decrypts the encryption key using the root key. Access to the root key is obtained through a process called unsealing the storage. The root key is stored together with the rest of the storage data, but it is encrypted with yet another key: the unseal key.
The module supports two modes, set by the management.mode parameter: Automatic (default) and Manual.
In the Automatic mode, the storage is initialized automatically on the first start of the module. During initialization, the unseal key and the root token are placed into the stronghold-keys secret in the d8-stronghold Kubernetes namespace. After initialization, the module automatically unseals the Stronghold cluster nodes.
In the automatic mode, when Stronghold nodes restart, the storage is also unsealed automatically without user intervention.
In the Manual mode, automatic initialization is disabled, the Dex and Kubernetes integrations are not configured, the stronghold-keys secret is not created, and the management.administrators parameter is unavailable. Initialize and unseal the storage yourself.
Access management
In the Automatic mode, after the storage is initialized, Stronghold creates the deckhouse_administrators policy, which is granted access to the web interface via Dex OIDC authentication.
Automatic connection of the current Deckhouse cluster to Stronghold is also configured for the secrets-store-integration module.
A hands-on walkthrough of delivering secrets to an application is available in the “Deckhouse Stronghold capabilities overview” course (in Russian).
To grant permissions to users in the admins group (group membership is passed from the IdP or LDAP in use via Dex), specify this group in the management.administrators array in ModuleConfig (available only when management.mode: Automatic; each item has a type of Group or User and a name):
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: stronghold
spec:
enabled: true
version: 1
settings:
management:
mode: Automatic
administrators:
- type: Group
name: adminsTo grant administrator permissions to the manager and securityoperator users, you can use the following parameters in ModuleConfig:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: stronghold
spec:
enabled: true
version: 1
settings:
management:
mode: Automatic
administrators:
- type: User
name: manager@mycompany.tld
- type: User
name: securityoperator@mycompany.tldAlthough access can be assigned to individual users, they must belong to at least one group to authenticate via OIDC.
Later, you can create users in Stronghold with different access permissions to secrets using the built-in storage mechanism.
First launch
Before enabling the Stronghold module for the first time (with an empty storageClass), make sure that the /var/lib/deckhouse/stronghold directory does not exist on the file system of the nodes where Stronghold nodes will run (master nodes by default), and that the stronghold module is disabled.
Experience with the kubectl utility is required.
Below are options for organizing access to the module via the Ingress inlet, followed by the process of enabling the module and checking that it works.
Ways to organize access via the Ingress inlet
ClusterIssuer LetsEncrypt
This certificate issuance method is configured by default. However, it is suitable only for services reachable from the Internet (and not for internal networks). To check availability:
Get the address of the authentication platform:
d8 k -n d8-user-authn get ing dex # Expected output: # NAME CLASS HOSTS ADDRESS PORTS AGE # dex nginx dex.mycompany.tld 34.85.243.109 80, 443 4d20hThe
HOSTScolumn contains the domain to check, and theADDRESScolumn contains its IP address. Now make sure that the domain name points to this IP address. To do this, run the command:nslookup dex.mycompany.tld 8.8.8.8 # Expected output: # ... # Name: dex.mycompany.tld # Address: 34.85.243.109 # ... # Or: dig @8.8.8.8 dex.mycompany.tld # Expected output: # ... # ;; ANSWER SECTION: # dex.mycompany.tld. 3600 IN A 34.85.243.109 # ...If the response is an
NXDOMAINerror, configure the user’s DNS.Open https://dex.mycompany.tld/healthz in a browser or run
curl -kL https://dex.mycompany.tld/healthz. The response must beHealth check passed.Check that the Ingress controller handles requests to your
stronghold.mycompany.tldsubdomain. Open https://stronghold.mycompany.tld in a browser or withcurl -kL. A 404 error must be returned.
ClusterIssuer with a self-signed certificate authority
This option is suitable if you want to use your own self-signed certificate authority. As an example, the already created selfsigned ClusterIssuer is used. To add an Issuer or ClusterIssuer with your own self-signed certificate authority, see the official documentation.
This method works both with a public domain name and with access from the internal network only.
Edit the global module settings. To do this, run d8 k edit mc global.
Add the settings.modules.https.certManager.clusterIssuerName: selfsigned parameter. The resulting module configuration:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: global
spec:
settings:
modules:
https:
certManager:
# The only parameter to add.
clusterIssuerName: selfsigned
publicDomainTemplate: '%s.mycompany.tld'
version: 1Next, edit the user-authn module settings. Run d8 k edit mc user-authn and change the settings.controlPlaneConfigurator.dexCAMode parameter to FromIngressSecret:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: user-authn
spec:
enabled: true
settings:
controlPlaneConfigurator:
# The parameter to change.
dexCAMode: FromIngressSecret
...Before starting the module, make sure the key services are reachable from the working network.
Get the address of the authentication platform:
d8 k -n d8-user-authn get ing dex # Expected output: # NAME CLASS HOSTS ADDRESS PORTS AGE # dex nginx dex.mycompany.tld 34.85.243.109 80, 443 4d20hThe
HOSTScolumn contains the domain to check, and theADDRESScolumn contains its IP address. Now make sure that the domain name points to this IP address. To do this, run the command:nslookup dex.mycompany.tld # Expected output: # ... # Name: dex.mycompany.tld # Address: 34.85.243.109 # ... # Or: dig dex.mycompany.tld # Expected output: # ... # ;; ANSWER SECTION: # dex.mycompany.tld. 3600 IN A 34.85.243.109 # ...If the response is an
NXDOMAINerror, configure the user’s DNS. If the domain is not reachable from the Internet, perform an additional step.As a temporary workaround, you can add the following line to the
/etc/hostsfile of your Unix system:34.85.243.109 dex.mycompany.tld stronghold.mycompany.tldOpen https://dex.mycompany.tld/healthz in a browser or run
curl -kL https://dex.mycompany.tld/healthz. The response must beHealth check passed.Check that the Ingress controller handles requests to your
stronghold.mycompany.tldsubdomain. Open https://stronghold.mycompany.tld in a browser or withcurl -kL. A 404 error must be returned.
Using a certificate file
Create a CA and a certificate, and then sign the certificate with this CA. If a CA already exists, you can sign the certificate with the existing CA. The certificate must be generated with the full chain (fullchain).
Below is the createCertificate.sh script, which uses openssl to create the required certificate and key pair
for the mycompany.tld domain (*.mycompany.tld).
#!/bin/bash
set -e
# CA name (CN).
caName="MyOrg-RootCA"
# Cluster domain name (see publicDomainTemplate).
publicDomain="mycompany.tld"
# Certificate name for the cluster (CN).
certName="kubernetes"
mkdir -p "${caName}"
cd "${caName}"
[ ! -f "${caName}.key" ] && openssl genrsa -out "${caName}.key" 4096
[ ! -f "${caName}.crt" ] && openssl req -x509 -new -nodes -key "${caName}.key" -sha256 -days 1826 -out "${caName}.crt" \
-subj "/CN=${caName}/O=MyOrganisation"
openssl req -new -nodes -out ${certName}.csr -newkey rsa:4096 -keyout "${certName}.key" \
-subj "/CN=${certName}/O=MyOrganisation"
# v3 ext file
cat > "${certName}.v3.ext" << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${publicDomain}
DNS.2 = *.${publicDomain}
EOF
openssl x509 -req -in "${certName}.csr" -CA "${caName}.crt" -CAkey "${caName}.key" -CAcreateserial -out "${certName}.crt" -days 730 -sha256 -extfile "${certName}.v3.ext"
cat "${certName}.crt" "${caName}.crt" > "${certName}_fullchain.crt"Using the resulting kubernetes.key and kubernetes_fullchain.crt files, create a secret in the d8-system namespace.
d8 k -n d8-system create secret tls mycompany-wildcard-tls --cert=kubernetes_fullchain.crt --key=kubernetes.keyTo use the resulting certificate in the cluster, bring the global configuration to the following form by running d8 k edit mc global:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: global
spec:
settings:
modules:
https:
customCertificate:
# The name of the Secret object containing the fullchain certificate and key.
secretName: mycompany-wildcard-tls
# Change the TLS mode for all modules.
mode: CustomCertificate
publicDomainTemplate: '%s.mycompany.tld'You also need to configure the user-authn module by setting controlPlaneConfigurator.dexCAMode to FromIngressSecret.
In this case, the CA is taken from the chain placed in the kubernetes_fullchain.crt file.
Example:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: user-authn
spec:
enabled: true
settings:
controlPlaneConfigurator:
dexCAMode: FromIngressSecret
...Before starting the module, make sure the key services are reachable from the working network.
Get the address of the authentication platform:
d8 k -n d8-user-authn get ing dex # Expected output: # NAME CLASS HOSTS ADDRESS PORTS AGE # dex nginx dex.mycompany.tld 34.85.243.109 80, 443 4d20hThe
HOSTScolumn contains the domain to check, and theADDRESScolumn contains its IP address. Now make sure that the domain name points to this IP address. To do this, run the command:nslookup dex.mycompany.tld # Expected output: # ... # Name: dex.mycompany.tld # Address: 34.85.243.109 # ... # Or: dig dex.mycompany.tld # Expected output: # ... # ;; ANSWER SECTION: # dex.mycompany.tld. 3600 IN A 34.85.243.109 # ...If the response is an
NXDOMAINerror, configure the user’s DNS. If the domain is not reachable from the Internet, perform an additional step.As a temporary workaround, you can add the following line to the
/etc/hostsfile of your Unix system:34.85.243.109 dex.mycompany.tld stronghold.mycompany.tldOpen https://dex.mycompany.tld/healthz in a browser or run
curl -kL https://dex.mycompany.tld/healthz. The response must beHealth check passed.Check that the Ingress controller handles requests to your
stronghold.mycompany.tldsubdomain. Open https://stronghold.mycompany.tld in a browser or withcurl -kL. A 404 error must be returned.
What to do if dex.mycompany.tld does not resolve via DNS
If the domain does not resolve via DNS and you plan to use the hosts file, add the load balancer address or the frontend node IP address to the cluster DNS for Dex to work.
You can use the kube-dns module for this, so that pods can reach the dex.mycompany.tld domain by name.
Example of getting the IP address for the nginx-load-balancer Ingress of the LoadBalancer type:
d8 k -n d8-ingress-nginx get svc nginx-load-balancer -o jsonpath='{ .spec.clusterIP }'Suppose the address is 34.85.243.109. The kube-dns module configuration for this address:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: kube-dns
spec:
version: 1
enabled: true
settings:
hosts:
- domain: dex.mycompany.tld
ip: 34.85.243.109Enabling the module
After organizing access, enable the stronghold module. Initialization and configuration of the integration with dex happen automatically.
d8 system module enable strongholdAfter the module starts:
- Make sure that a certificate for the stronghold.* domain exists by running
d8 k -n d8-stronghold get secret ingress-tls(or via the console). The Troubleshooting section describes solutions to possible problems with a missing certificate. - Make sure that https://stronghold.mycompany.tld/v1/sys/health is reachable.
- Check that the certificate issuer matches the CA certificate (optional).
Troubleshooting
Pods are in the ContainerCreating state and there is no Secret named ingress-tls
Check the status of the Stronghold pod:
d8 k -n d8-stronghold describe pod stronghold-0Find the line:
MountVolume.SetUp failed for volume "certificates" : secret "ingress-tls" not foundWhen using the ClusterIssuer with LetsEncrypt method, there may be a problem with the Let’s Encrypt certificate authority automatically creating a certificate for the stronghold.mycompany.tld domain.
Get the list of CertificateRequest objects:
d8 k -n d8-stronghold get certificaterequestFind the object whose name starts with stronghold-; in this example, it is stronghold-b5wc6.
Check its status:
d8 k -n d8-stronghold describe certificaterequest stronghold-b5wc6One possible cause is the too many certificates already issued for mycompany.tld error, especially if a free dynDNS service is used, for example, sslip.io or getmoss.site.
In this case, either wait until the rate limit expires or use another way to create a certificate for the stronghold.mycompany.tld domain (the selfsigned ClusterIssuer or manual certificate signing).
When the certificate is generated successfully, the CertificateRequest status must contain the following lines:
Message: Certificate fetched from issuer successfully
Reason: Issued
Status: True
Type: ReadyA Secret object of the kubernetes.io/tls type named ingress-tls must also appear.
Monitoring
In Deckhouse Platform, the module configures metrics collection and alerts automatically: no manual setup is required. For the metrics collection scheme, the list of alerts, and how to request metrics manually, see Monitoring in Deckhouse Platform.