The following sections describe how to configure TLS for Anchore API and/or Anchore Enterprise Services. Please note that the UI service currently does not support listening via TLS.
Internal TLS for Anchore Enterprise Services Helm deployments
graph TB
subgraph External Traffic
user[User]
kubernetes[Ingress Controller]
end
subgraph Services with Internal TLS
api[API]
policy[Policy]
catalog[Catalog]
analyzer[Analyzer]
reports[Reports]
reportsworker[Reports Worker]
notifications[Notifications]
dataSyncer[Data Syncer]
simplequeue[Simple Queue]
componentcatalog[Component Catalog]
end
subgraph Services Without TLS
ui[UI]
end
user -- HTTP/HTTPS --> kubernetes
kubernetes -- HTTPS --> api
kubernetes -- HTTP --> ui
api <--> policy
api <--> catalog
api <--> analyzer
api <--> reports
api <--> reportsworker
api <--> notifications
api <--> dataSyncer
api <--> simplequeue
api <--> componentcatalog
policy <--> catalog
catalog <--> analyzer
analyzer <--> reports
reports <--> reportsworker
reportsworker <--> notifications
notifications <--> dataSyncer
dataSyncer <--> simplequeue
componentcatalog <--> catalog
componentcatalog <--> simplequeueThe following will configure Anchore Enterprise internal services to communicate with one another via TLS.
This script (for Linux) is provided as a demonstration of how to generate certificates (generate-anchore-tls-certs.sh):
#!/bin/bash
export NAMESPACE="$1";
export RELEASE="$2";
export SANS="DNS:*.${NAMESPACE}.svc.cluster.local,\
DNS:${RELEASE}-enterprise-api,\
DNS:${RELEASE}-enterprise-analyzer,\
DNS:${RELEASE}-enterprise-catalog,\
DNS:${RELEASE}-enterprise-notifications,\
DNS:${RELEASE}-enterprise-policy,\
DNS:${RELEASE}-enterprise-reports,\
DNS:${RELEASE}-enterprise-reportsworker,\
DNS:${RELEASE}-enterprise-simplequeue,\
DNS:${RELEASE}-enterprise-ui,\
DNS:${RELEASE}-enterprise-datasyncer,\
DNS:${RELEASE}-enterprise-componentcatalog"
# NOTE: This ends up being the filename of resulting certificates
SERVER_NAME="anchore"
ANCHORE_TLS=./anchore-tls
SCRIPT=$(readlink -f "$0")
DIR=$(dirname "$SCRIPT")
echo "Making ANCHORE_TLS dir..."
mkdir -p ${ANCHORE_TLS}
cd ${ANCHORE_TLS}
# Customize as needed
CORPORATION=Anchore
GROUP=K8S
CITY=Atlanta
STATE=Georgia
COUNTRY=US
CERT_AUTH_PASS=`openssl rand -base64 32`
echo $CERT_AUTH_PASS > cert_auth_password
CERT_AUTH_PASS=`cat cert_auth_password`
# create the certificate authority
openssl \
req \
-subj "/CN=$SERVER_NAME.ca/OU=$GROUP/O=$CORPORATION/L=$CITY/ST=$STATE/C=$COUNTRY" \
-new \
-x509 \
-passout pass:$CERT_AUTH_PASS \
-keyout ca-cert.key \
-out ca-cert.crt \
-days 3650
# create client private key (used to decrypt the cert we get from the CA)
openssl genrsa -out $SERVER_NAME.key
# create the CSR(Certificate Signing Request)
openssl \
req \
-new \
-nodes \
-subj "/CN=$SERVER_NAME/OU=$GROUP/O=$CORPORATION/L=$CITY/ST=$STATE/C=$COUNTRY" \
-sha256 \
-extensions v3_req \
-reqexts SAN \
-key $SERVER_NAME.key \
-out $SERVER_NAME.csr \
-config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=$SANS")) \
-days 3650
# sign the certificate with the certificate authority
openssl \
x509 \
-req \
-days 3650 \
-in $SERVER_NAME.csr \
-CA ca-cert.crt \
-CAkey ca-cert.key \
-CAcreateserial \
-out $SERVER_NAME.crt \
-extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=$SANS")) \
-extensions SAN \
-passin pass:$CERT_AUTH_PASS
# Create key pem
cat $SERVER_NAME.key > $SERVER_NAME-key.pem
# Create cert pem
cat $SERVER_NAME.crt > $SERVER_NAME.pem
cat ca-cert.crt >> $SERVER_NAME.pem
cd ..
cat << EOF > anchore-tls-certs.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: anchore-tls-certs
namespace: $NAMESPACE
type: Opaque
data:
internal-cert.pem: $(base64 anchore-tls/$SERVER_NAME.pem --wrap 0)
internal-cert-key.pem: $(base64 anchore-tls/$SERVER_NAME-key.pem --wrap 0)
ca.pem: $(base64 anchore-tls/ca-cert.crt --wrap 0)
EOF
kubectl apply -n $NAMESPACE -f anchore-tls-certs.yaml
If Custom CA certificates are required for LDAP or Postgres be sure to append them to the anchore-tls/ca-cert.crt & anchore-tls/anchore.pem file.
The script can be called as follows:
chmod +x generate-anchore-tls-certs.sh
# Provide values for your kubernetes namespace containing anchore and your helm release
./generate-anchore-tls-certs.sh $NAMESPACE $RELEASE
Make the following adjustments in your helm values file. certStoreSecretName mounts the secret at /home/anchore/certs/, and the server block under anchoreConfig applies to every service:
certStoreSecretName: anchore-tls-certs
anchoreConfig:
internal_ssl_verify: false
server:
ssl_enable: true
ssl_cert: /home/anchore/certs/internal-cert.pem
ssl_key: /home/anchore/certs/internal-cert-key.pem
ui:
ldapsRootCaCertName: ca.pem
To enable TLS for a single service rather than all of them, use the same server block under that service, for example anchoreConfig.apiext.server.
ui.ldapsRootCaCertName is required whenever internal TLS uses a private CA, even if you do not use LDAP. It is what sets NODE_EXTRA_CA_CERTS for the UI, and the UI is a Node.js application that will not trust the CA without it. Omitting it leaves the UI pod permanently unready, logging Error connecting to Enterprise services: self-signed certificate in certificate chain on a retry loop while every other service comes up healthy.anchoreConfig.internalServicesSSL is not supported by the version 4 chart line, which is the line that deploys Anchore Enterprise v6. It has been replaced by the server block shown above. The version 3 chart line, which deploys v5, still accepts it. The chart fails fast rather than ignoring it: if internalServicesSSL is still present in your values, helm install and helm upgrade stop with the message “anchoreConfig.internalServicesSSL is no longer supported”. Its verifyCerts key is now anchoreConfig.internal_ssl_verify, and certSecretCertFileName and certSecretKeyFileName are now the full paths ssl_cert and ssl_key.You will need to perform a Helm install or upgrade to apply all the changes and restart all the pods.
If using an ingress controller see the next section.
Separating API & UI Ingress for Helm deployments
If you are using ingress to access Anchore Enterprise API & Anchore Enterprise GUI then you will need to separate the ingress configuration if you configure either External or Internal TLS. Since API supports TLS and UI does not once TLS is enabled for API the ingress controller will need to send encrypted traffic to API and unencrypted traffic to UI.
Make the following change to your helm values file to configure the ingress to use TLS to communicate with the API service:
ingress:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
# These are for other reasons besides internal TLS
nginx.ingress.kubernetes.io/proxy-body-size: '0'
nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
uiHosts:
- anchore-api.yourdomain.com
Add an ingress directly in kubernetes for the UI:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: anchore-ingress-ui
annotations:
# These are for other reasons besides internal TLS
nginx.ingress.kubernetes.io/proxy-body-size: '0'
nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
spec:
ingressClassName: nginx # NOTE: This could be another value such as alb
tls: []
rules:
- host: anchore-ui.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: anchore-enterprise-ui # Ensure this matches the name of the Anchore UI service
port:
number: 80
Apply UI Ingress changes:
kubectl apply -n $NAMESPACE -f anchore-ingress-ui.yaml
External TLS for Anchore Enterprise API Service
Please note that configuring Internal TLS above also includes External TLS. If you performed the steps above then this is not necessary.
In the following example the external API service is configured to listen on port 443 and is configured with a certificate for its external hostname anchore.example.com
Each service published in config.yaml (apiext, catalog, simplequeue, analyzer, policy_engine, reports, reports_worker, notifications and data_syncer) can be configured to use transport level security. The component catalog is configured separately, in bootstrap_ng.yaml — see Component Catalog TLS below.
The TLS settings live in the service’s server block, while the address settings live directly on the service:
services:
apiext:
enabled: True
endpoint_hostname: 'anchore-api.mydomain.com'
listen: '0.0.0.0'
port: 443
server:
ssl_enable: True
ssl_cert: '/config/anchore-ex.crt'
ssl_key: '/config/anchore-ex.key'
ssl_chain: '/config/anchore-ex.crt'
ssl_* settings must be nested under server. Placing them directly on the service, as earlier versions of this page showed, does not enable TLS: the keys are discarded while the configuration loads, no warning is logged, and the service starts and reports healthy on plain HTTP. Verify with curl after enabling TLS rather than relying on a clean startup.| Setting | Level | Notes |
|---|---|---|
| enabled | service | If the service is enabled |
| endpoint_hostname | service | DNS name of service |
| listen | service | IP address of interface on which the service should listen (use ‘0.0.0.0’ for all - default) |
| port | service | Port on which service should listen |
| ssl_enable | server | Enable transport level security |
| ssl_cert | server | Name, including full path, of the certificate file |
| ssl_key | server | Name, including full path, of the private key file |
| ssl_chain | server | [optional] Name, including full path, of the certificate chain |
The certificate files should be placed on a path accessible to the Anchore Enterprise service, for example in the /config directory which is typically mapped as a volume into the container. Note that the location outside the container will depend on your configuration - for example if you are volume mounting ‘/path/to/aevolume/config/’ on the docker host to ‘/config’ within the container, you’ll need to place the ssl files in ‘/path/to/aevolume/config/’ on the docker host, so that they are accessible in ‘/config/’ inside the container, before starting the service.
The ssl_chain file is optional and may be required by some certificate authorities. If your certificate authority provides a chain certificate then include it within the configuration.
Note: While a certificate may be purchased from a well-known and trusted certificate authority in some cases the certificate is signed by an intermediate certificate which is not included within a TLS/SSL clients trust stores. In these cases the intermediate certificate is signed by the certificate authority however without the full ‘chain’ showing the provenance and integrity of the certificate the TLS/SSL client may not trust the certificate.
Any certificates used by the Anchore Enterprise services need to be trusted by all other Anchore Enterprise services.
If an internal certificate authority is used, add the root certificate for that CA to Anchore Enterprise as described in Custom Certificate Authority.
Alternatively, disable verification of internal service certificates by setting internal_ssl_verify to False. The setting defaults to True, which enables verification, so it must be set explicitly to turn verification off:
internal_ssl_verify: False
This is a top-level setting, not a per-service one, and it appears in both config.yaml and bootstrap_ng.yaml. Set it in both files if you supply your own, so that the component catalog and the other services agree.
Component Catalog TLS
The component catalog reads its service configuration from bootstrap_ng.yaml rather than config.yaml, so its TLS settings live there. The keys are the same, again nested under server:
services:
component_catalog:
endpoint_hostname: ${ANCHORE_ENDPOINT_HOSTNAME}
port: ${ANCHORE_COMPONENT_CATALOG_PORT}
server:
ssl_enable: true
ssl_cert: /path/to/cert.pem
ssl_key: /path/to/key.pem
ssl_chain: /path/to/chain.pem
When ssl_enable is true, both ssl_cert and ssl_key must be set. ssl_chain is optional.
For more on the component catalog configuration files and how to supply your own, see General Configuration.