Source code for nephos.fabric.ca

#   Copyright [2018] [Alejandro Vicente Grabovetsky via AID:Tech]
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at#
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

from os import path
from time import sleep

from kubernetes.client.rest import ApiException
from nephos.fabric.settings import get_namespace, get_version
from nephos.fabric.utils import get_helm_pod
from nephos.helpers.helm import (
    HelmPreserve,
    helm_check,
    helm_extra_vars,
    helm_install,
    helm_upgrade,
)
from nephos.helpers.k8s import ingress_read, secret_read
from nephos.helpers.misc import execute_until_success

CURRENT_DIR = path.abspath(path.split(__file__)[0])


# Core sub-functions
[docs]def ca_chart(opts, release, upgrade=False, verbose=False): """Deploy CA Helm chart to K8S. Args: opts (dict): Nephos options dict. release (str): Name of the Helm Chart release. upgrade (bool): Do we upgrade the deployment? False by default. verbose (bool): Verbosity. False by default. """ values_dir = opts["core"]["dir_values"] repository = opts["core"]["chart_repo"] ca_namespace = get_namespace(opts, ca=release) # PostgreSQL (Upgrades here are dangerous, deactivated by default) # Upgrading database is risky, so we disallow it by default if not upgrade: version = get_version(opts, "postgresql") config_yaml = "{dir}/postgres-ca/{name}-pg.yaml".format( dir=values_dir, name=release ) extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml) helm_install( "stable", "postgresql", "{}-pg".format(release), ca_namespace, extra_vars=extra_vars, verbose=verbose, ) helm_check("postgresql", "{}-pg".format(release), ca_namespace) psql_secret = secret_read( "{}-pg-postgresql".format(release), ca_namespace, verbose=verbose ) # Different key depending of PostgreSQL version psql_password = ( psql_secret.get("postgres-password") or psql_secret["postgresql-password"] ) # Fabric CA version = get_version(opts, "hlf-ca") env_vars = [("externalDatabase.password", psql_password)] config_yaml = "{dir}/hlf-ca/{name}.yaml".format(dir=values_dir, name=release) if not upgrade: extra_vars = helm_extra_vars( version=version, config_yaml=config_yaml, env_vars=env_vars ) helm_install( repository, "hlf-ca", release, ca_namespace, extra_vars=extra_vars, verbose=verbose, ) else: preserve = ( HelmPreserve( ca_namespace, "{}-hlf-ca--ca".format(release), "CA_ADMIN", "adminUsername", ), HelmPreserve( ca_namespace, "{}-hlf-ca--ca".format(release), "CA_PASSWORD", "adminPassword", ), ) extra_vars = helm_extra_vars( version=version, config_yaml=config_yaml, env_vars=env_vars, preserve=preserve, ) helm_upgrade( repository, "hlf-ca", release, extra_vars=extra_vars, verbose=verbose ) helm_check("hlf-ca", release, ca_namespace)
[docs]def ca_enroll(pod_exec): """Enroll CA. Enroll the Certificate Authority (CA) identity within the running CA pod. This is a necessary step for the CA to function. Args: pod_exec: A pod executor instance bound to the CA. """ alive = False while not alive: res = pod_exec.logs() if "Listening on" in res: alive = True else: sleep(15) # Enroll CA Admin if necessary ca_cert, _ = pod_exec.execute( "cat /var/hyperledger/fabric-ca/msp/signcerts/cert.pem" ) if not ca_cert: enrolled_id = False while not enrolled_id: res, err = pod_exec.execute( "bash -c 'fabric-ca-client enroll -d -u http://$CA_ADMIN:$CA_PASSWORD@$SERVICE_DNS:7054'" ) if not err: enrolled_id = True else: sleep(15)
[docs]def check_ca(ingress_host, cacert=None, verbose=False): """Check that the CA Ingress is responsive. Args: ingress_host (str): Ingress host for the CA. cacert (str): Path of the CA cert. verbose (bool): Verbosity. False by default. """ # Check that CA ingress is operational command = "curl https://{ingress}/cainfo".format(ingress=ingress_host) if cacert: command += " --cacert {}".format(cacert) execute_until_success(command, verbose=verbose)
# Runner
[docs]def setup_ca(opts, upgrade=False, verbose=False): """Setup CA. Setup involves enrolling the CA admin, checking the Ingress is responsive. Args: opts (dict): Nephos options dict. upgrade (bool): Do we upgrade the deployment? False by default. verbose (bool): Verbosity. False by default. """ for ca_name, ca_values in opts["cas"].items(): ca_namespace = get_namespace(opts, ca=ca_name) # Install Charts ca_chart(opts=opts, release=ca_name, upgrade=upgrade, verbose=verbose) # Obtain CA pod and Enroll pod_exec = get_helm_pod( namespace=ca_namespace, release=ca_name, app="hlf-ca", verbose=verbose ) ca_enroll(pod_exec) # Get CA Ingress and check it is running try: # Get ingress of CA ingress_urls = ingress_read( ca_name + "-hlf-ca", namespace=ca_namespace, verbose=verbose ) except ApiException: print("No ingress found for CA") continue # Check the CA is running check_ca( ingress_host=ingress_urls[0], cacert=ca_values.get("tls_cert"), verbose=verbose, )