github.com/IBM-Blockchain/fabric-operator@v1.0.4/integration/helper/ca.go (about)

     1  /*
     2   * Copyright contributors to the Hyperledger Fabric Operator project
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at:
     9   *
    10   * 	  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package helper
    20  
    21  import (
    22  	"context"
    23  	"crypto/tls"
    24  	"crypto/x509"
    25  	"fmt"
    26  	"io/ioutil"
    27  	"net/http"
    28  	"os"
    29  	"os/exec"
    30  	"path/filepath"
    31  	"strings"
    32  	"time"
    33  
    34  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    35  	"github.com/IBM-Blockchain/fabric-operator/integration"
    36  	ibpclient "github.com/IBM-Blockchain/fabric-operator/pkg/client"
    37  
    38  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    39  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    40  	"k8s.io/client-go/kubernetes"
    41  
    42  	"sigs.k8s.io/yaml"
    43  )
    44  
    45  func CreateCA(crClient *ibpclient.IBPClient, ca *current.IBPCA) error {
    46  	result := crClient.Post().Namespace(ca.Namespace).Resource("ibpcas").Body(ca).Do(context.TODO())
    47  	err := result.Error()
    48  	if !k8serrors.IsAlreadyExists(err) {
    49  		return err
    50  	}
    51  	return nil
    52  }
    53  
    54  type CA struct {
    55  	Domain     string
    56  	Name       string
    57  	Namespace  string
    58  	WorkingDir string
    59  
    60  	CR       *current.IBPCA
    61  	CRClient *ibpclient.IBPClient
    62  	KClient  *kubernetes.Clientset
    63  
    64  	integration.NativeResourcePoller
    65  }
    66  
    67  func (ca *CA) PollForCRStatus() current.IBPCRStatusType {
    68  	crStatus := &current.IBPCA{}
    69  
    70  	result := ca.CRClient.Get().Namespace(ca.Namespace).Resource("ibpcas").Name(ca.Name).Do(context.TODO())
    71  	// Not handling this because - integration test
    72  	_ = result.Into(crStatus)
    73  
    74  	return crStatus.Status.Type
    75  }
    76  
    77  func (ca *CA) HealthCheck(url string, cert []byte) bool {
    78  	rootCertPool := x509.NewCertPool()
    79  	rootCertPool.AppendCertsFromPEM(cert)
    80  
    81  	transport := http.DefaultTransport
    82  	transport.(*http.Transport).TLSClientConfig = &tls.Config{
    83  		RootCAs:    rootCertPool,
    84  		MinVersion: tls.VersionTLS12, // TLS 1.2 recommended, TLS 1.3 (current latest version) encouraged
    85  	}
    86  
    87  	client := http.Client{
    88  		Transport: transport,
    89  		Timeout:   30 * time.Second,
    90  	}
    91  
    92  	_, err := client.Get(url)
    93  	if err != nil {
    94  		return false
    95  	}
    96  
    97  	return true
    98  }
    99  
   100  func (ca *CA) ConnectionProfile() (*current.CAConnectionProfile, error) {
   101  	cm, err := ca.KClient.CoreV1().ConfigMaps(ca.Namespace).Get(context.TODO(), fmt.Sprintf("%s-connection-profile", ca.CR.Name), metav1.GetOptions{})
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	data := cm.BinaryData["profile.json"]
   107  
   108  	profile := &current.CAConnectionProfile{}
   109  	err = yaml.Unmarshal(data, profile)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	return profile, nil
   115  }
   116  
   117  func (ca *CA) Address() string {
   118  	return fmt.Sprintf("%s-%s-ca.%s", ca.Namespace, ca.Name, ca.Domain)
   119  }
   120  
   121  func (ca *CA) Register(name string, secret string, userType string) *exec.Cmd {
   122  	url := fmt.Sprintf("https://%s", ca.Address())
   123  	args := []string{
   124  		"--tls.certfiles", ca.TLSPath(),
   125  		"--id.name", name,
   126  		"--id.secret", secret,
   127  		"--id.type", userType,
   128  		"-u", url,
   129  		"-d",
   130  	}
   131  	return GetCommand(filepath.Join(ca.WorkingDir, "bin/fabric-ca-client register"), args...)
   132  }
   133  
   134  func (ca *CA) Enroll(name string, secret string) *exec.Cmd {
   135  	url := fmt.Sprintf("https://%s:%s@%s", name, secret, ca.Address())
   136  	args := []string{
   137  		"--tls.certfiles", ca.TLSPath(),
   138  		"-u", url,
   139  		"-d",
   140  	}
   141  	return GetCommand(filepath.Join(ca.WorkingDir, "bin/fabric-ca-client enroll"), args...)
   142  }
   143  
   144  func (ca *CA) DeleteIdentity(name string) *exec.Cmd {
   145  	url := fmt.Sprintf("https://%s", ca.Address())
   146  	args := []string{
   147  		name,
   148  		"--tls.certfiles", ca.TLSPath(),
   149  		"-u", url,
   150  		"-d",
   151  	}
   152  	return GetCommand(filepath.Join(ca.WorkingDir, "bin/fabric-ca-client identity remove"), args...)
   153  }
   154  
   155  func (ca *CA) TLSToFile(cert []byte) error {
   156  	err := os.MkdirAll(filepath.Dir(ca.TLSPath()), 0750)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	err = ioutil.WriteFile(ca.TLSPath(), cert, 0600)
   161  	if err != nil {
   162  		return err
   163  	}
   164  	return nil
   165  }
   166  
   167  func (ca *CA) TLSPath() string {
   168  	return filepath.Join(ca.WorkingDir, ca.Name, "tls-cert.pem")
   169  }
   170  
   171  func (ca *CA) JobWithPrefixFound(prefix, namespace string) bool {
   172  	jobs, err := ca.KClient.BatchV1().Jobs(namespace).List(context.TODO(), metav1.ListOptions{})
   173  	if err != nil {
   174  		return false
   175  	}
   176  
   177  	for _, job := range jobs.Items {
   178  		if strings.HasPrefix(job.GetName(), prefix) {
   179  			return true
   180  		}
   181  	}
   182  
   183  	return false
   184  }