TLS / SSL
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] 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 policy <--> catalog catalog <--> analyzer analyzer <--> reports reports <--> reportsworker reportsworker <--> notifications notifications <--> dataSyncer dataSyncer <--> simplequeue
The following will configure Anchore Enterprise internal services to communicate with one another via TLS.
This script 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-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"
# 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(Certitificate 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: anchore-tls-certs
anchoreConfig:
internalServicesSSL:
enabled: true
verifyCerts: false
certSecretKeyFileName: internal-cert-key.pem
certSecretCertFileName: internal-cert.pem
ui:
ldapsRootCaCertName: ca.pem
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 UI then you will need to seperate 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 optional
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: []
Add an ingress directly in kubernetes for the UI:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: anchore-ingress-ui
annotations:
# These are optional
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.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 the Anchore Enterprise configuration (apiext, catalog, simplequeue, analyzer, policy_engine and kubernetes_webhook) can be configured to use transport level security.
services:
apiext:
enabled: True
endpoint_hostname: 'anchore.example.com'
listen: '0.0.0.0'
port: 443
ssl_enable: True
ssl_cert: '/config/anchore-ex.crt'
ssl_key: '/config/anchore-ex.key'
ssl_chain: '/config/anchore-ex.crt'
Setting | Notes |
---|---|
enabled | If the service is enabled |
endpoint_hostname | DNS name of service |
listen | IP address of interface on which the service should listen (use ‘0.0.0.0’ for all - default) |
port | Port on which service should listen. |
ssl_enable | Enable transport level security |
ssl_cert | name, including full path of private key file. |
ssl_chain | [optional] name, including full path of 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 the root certificate for the internal CA can be added to the Anchore Enterprise using the following procedure or SSL verification can be disabled by setting the following parameter:
internal_ssl_verify: True