In this blog post, I am going to cover the following stuff,
- Create self-signed certificates using the OpenSSL utility
- Create a Private Docker registry, use the self-signed certificate created in step 1 and enable basic authentication using htpasswd
- Enable Openshift to serve from a private docker registry
What is a Self Signed Certificate?
Before creating certificates, let's understand what a self-signed certificate is. A self-signed certificate is a certificate signed by its creator rather than by an official certificate authority(CA). Browsers or operating systems do not trust self-signed certificates unless you explicitly tell them to trust the certificate.
Why Use Self-Signed Certificates?
There are some use cases where it is okay to use self-signed certificates. For instance, you can use self-signed certificates to set up a test or an internal development environment.
Creating self-signed certificates is very easy and does not require any third-party tools. To create self-signed certificates, you can use the OpenSSL utility pre-installed on most Linux distributions.
Creating self-signed certificates using the OpenSSL utility:
We will use the OpenSSL tool to generate keys and certificates. You can find this tool in most of the Linux distributions by default. If not, install it using your package manager. I am using Fedora here.
sudo dnf install -y openssl
You can also find packages for Windows, MAC, and Linux flavors.
Create Certificate Authority
First, we must create a private key and certificate for the Certificate Authority(CA). The CA is used to sign the server certificate we will generate later.
Run the following command to create a private key and certificate for the CA. You can use any name for the CA. I am using ca here.
Create a directory to store all the keys and certificates. You can make this directory anywhere you want. I am creating this inside my home directory.
mkdir openssl && cd openssl
Now execute the following openssl
command to create a rootCA.key
private key and rootCA.crt
. Replace registry.goglides.dev with your domain name or IP address.
openssl req -x509 \
-sha256 -days 356 \
-nodes \
-newkey rsa:2048 \
-subj "/CN=registry.goglides.dev/C=US/L=San Fransisco" \
-keyout rootCA.key -out rootCA.crt
Create Certificate for registry.goglides.dev
- Create the Server Private Key
openssl genrsa -out server.key 2048
- Create the Server CSR (Certificate Signing Request) Configuration
cat > csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[ dn ]
C = US
ST = Colorado
L = Denver
O = Goglides
OU = Goglides Dev
CN = registry.goglides.dev
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = registry.goglides.dev
DNS.2 = www.registry.goglides.dev
IP.1 = 192.168.7.88
IP.2 = 192.168.7.203
EOF
- Generate Certificate Signing Request (CSR) Using Server Private Key
openssl req -new -key server.key -out server.csr -config csr.conf
- Create an external file
cat > cert.conf <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = registry.goglides.dev
EOF
- Generate an SSL certificate With a self-signed CA
openssl x509 -req \
-in server.csr \
-CA rootCA.crt -CAkey rootCA.key \
-CAcreateserial -out server.crt \
-days 365 -extensions cert.conf
- Create htpasswd file for the registry.goglides.dev
htpasswd -bBc htpasswd.goglides.dev goglides-dev SecureSecrets
In above command
-
-b
Use the password from the command line rather than prompting it. -
-B
Force bcrypt encryption of the password, Only bcrypt is supported at the moment -
-c
Create a new file htpasswd.goglides.dev with the given username and password
If the htpasswd.goglides.dev file is missing, the file will be created and provisioned with a default user and an automatically generated password. The password will be printed to stdout. You can check container logs using docker logs registry
for the password; the default username is docker.
Create docker config
cat <<EOF > config.yml
version: 0.1
http:
secret: AwesomeSecret123
host: https://registry.goglides.dev
auth:
htpasswd:
realm: basic-realm
path: /etc/docker/registry/htpasswd.goglides.dev
storage:
filesystem:
rootdirectory: /var/lib/registry
maxthreads: 100
EOF
Create a docker registry
mkdir certs
cp server.crt certs/server.crt
cp server.key certs/server.key
And run the registry as follows,
docker run -d \
--restart=always \
--name registry \
-v "$(pwd)"/htpasswd.goglides.dev:/etc/docker/registry/htpasswd.goglides.dev \
-v "$(pwd)"/config.yml:/etc/docker/registry/config.yml \
-v "$(pwd)"/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/server.key \
-p 443:443 \
registry:2
Verification
Now verify docker login, add 127.0.0.1 registry.goglides.dev to /etc/hosts, and run following command
docker login registry.goglides.dev -u goglides-dev -p SecureSecrets
Output:
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
Create Kubernetes secrets
- Create Kubernetes as follows so that you can pass this secret to imagePullSecrets later on
oc create secret docker-registry docker-pull-secret --docker-server=https://registry.goglides.dev/ --docker-username=goglides-dev --docker-password='SecureSecrets'
If you do not want to pass imagePullSecrets and your application is using a default
service account, you can link this secret to default service account as follows,
oc secrets link default docker-pull-secret --for=pull
Allow the docker registry to be used by the OpenShift container platform
- Create a configMap with
server.crt
as follows,
oc create configmap external-registry-config -n openshift-config --from-file=registry.goglides.dev=certs/server.crt
Now patch the image.config.openshift.io/cluster
object,
oc patch image.config.openshift.io/cluster --patch '{"spec":{"additionalTrustedCA":{"name":"external-registry-config"}}}' --type=merge
You can verify the object using the following command,
oc get image.config.openshift.io/cluster -o json | jq .spec.additionalTrustedCA
Output:
{
"name": "external-registry-config"
}
Verify that imagePullSecrets are there in the service account
-
oc get sa default -o json | jq '.imagePullSecrets[]'
Output:
{
"name": "default-dockercfg-stgqk"
}
{
"name": "docker-pull-secret"
}
Verification
Let's verify whether OpenShift can pull the image from this registry or not. First, publish an image to this docker registry.
docker pull nginx
docker tag nginx registry.goglides.dev/nginx
And push this image to registry
docker push registry.goglides.dev/nginx
Output:
Using default tag: latest
The push refers to repository [registry.goglides.dev/nginx]
de100bd247e0: Pushed
1d561d938628: Pushed
c03189a5ef70: Pushed
305b0db3a210: Pushed
1c99a7efe9d9: Pushed
43b3c4e3001c: Pushed
latest: digest: sha256:33cef86aae4e8487ff23a6ca16012fac28ff9e7a5e9759d291a7da06e36ac958 size: 1570
You can validate the image is present or not as follows,
curl --cacert server.crt -u 'goglides-dev:SecureSecrets' https://registry.goglides.dev/v2/_catalog
Output:
{"repositories":["nginx"]}
Now create a pod to pull from this registry,
oc run nginx --image registry.goglides.dev/nginx
Output:
pod/nginx created
The nginx pod should be up and running.
oc get pods
Output:
nginx 1/1 Running 0 41s
Top comments (0)