github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/common/config/hsmconfig.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 config
    20  
    21  import (
    22  	"context"
    23  
    24  	"github.com/pkg/errors"
    25  
    26  	corev1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/types"
    29  
    30  	"sigs.k8s.io/controller-runtime/pkg/client"
    31  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    32  	"sigs.k8s.io/yaml"
    33  )
    34  
    35  var log = logf.Log.WithName("config")
    36  
    37  // Client defines the contract to get resources from clusters
    38  type Client interface {
    39  	Get(ctx context.Context, key client.ObjectKey, obj client.Object) error
    40  }
    41  
    42  // ReadHSMConfig reads hsm configuration from 'ibp-hsm-config', and key 'ibp-hsm-config.yaml'
    43  // from data
    44  func ReadHSMConfig(client Client, instance metav1.Object) (*HSMConfig, error) {
    45  	// NOTE: This is hard-coded because this name should never be different
    46  	name := "ibp-hsm-config"
    47  
    48  	cm := &corev1.ConfigMap{}
    49  	err := client.Get(
    50  		context.TODO(),
    51  		types.NamespacedName{
    52  			Name:      name,
    53  			Namespace: instance.GetNamespace(),
    54  		},
    55  		cm,
    56  	)
    57  	if err != nil {
    58  		return nil, errors.Wrap(err, "failed to get hsm config 'ibp-hsm-config'")
    59  	}
    60  
    61  	hsmConfig := &HSMConfig{}
    62  	err = yaml.Unmarshal([]byte(cm.Data["ibp-hsm-config.yaml"]), hsmConfig)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	return hsmConfig, nil
    68  }
    69  
    70  // HSMConfig defines the configuration parameters for HSMs
    71  type HSMConfig struct {
    72  	Type       string          `json:"type,omitempty"`
    73  	Version    string          `json:"version,omitempty"`
    74  	Library    Library         `json:"library"`
    75  	MountPaths []MountPath     `json:"mountpaths"`
    76  	Envs       []corev1.EnvVar `json:"envs,omitempty"`
    77  	Daemon     *Daemon         `json:"daemon,omitempty"`
    78  }
    79  
    80  // Library represents the configuration for an HSM library
    81  type Library struct {
    82  	FilePath           string `json:"filepath"`
    83  	Image              string `json:"image"`
    84  	AutoUpdateDisabled bool   `json:"autoUpdateDisabled,omitempty"`
    85  	Auth               *Auth  `json:"auth,omitempty"`
    86  }
    87  
    88  // BuildPullSecret builds the string secret into the type expected by kubernetes
    89  func (h *HSMConfig) BuildPullSecret() corev1.LocalObjectReference {
    90  	if h.Library.Auth != nil {
    91  		return h.Library.Auth.BuildPullSecret()
    92  	}
    93  	return corev1.LocalObjectReference{}
    94  }
    95  
    96  // GetVolumes builds the volume spec into the type expected by kubernetes, by default
    97  // the volume source is empty dir with memory as the storage medium
    98  func (h *HSMConfig) GetVolumes() []corev1.Volume {
    99  	volumes := []corev1.Volume{}
   100  	for _, mount := range h.MountPaths {
   101  		// Skip building volume if using PVC, the PVC is known to the caller of method.
   102  		// The caller will build the proper PVC volume by setting the appropriate claim name.
   103  		if !mount.UsePVC {
   104  			volumes = append(volumes, mount.BuildVolume())
   105  		}
   106  	}
   107  	return volumes
   108  }
   109  
   110  // GetVolumeMounts builds the volume mount spec into the type expected by kubernetes
   111  func (h *HSMConfig) GetVolumeMounts() []corev1.VolumeMount {
   112  	volumeMounts := []corev1.VolumeMount{}
   113  	for _, mount := range h.MountPaths {
   114  		// Skip building volume mount if using PVC, the PVC is known to the caller of method.
   115  		// The caller will build the proper PVC volume mount with the mount path specified
   116  		// in the HSM config
   117  		if !mount.UsePVC {
   118  			volumeMounts = append(volumeMounts, mount.BuildVolumeMount())
   119  		}
   120  	}
   121  	return volumeMounts
   122  }
   123  
   124  // GetEnvs builds the env var spec into the type expected by kubernetes
   125  func (h *HSMConfig) GetEnvs() []corev1.EnvVar {
   126  	return h.Envs
   127  }
   128  
   129  // Auth represents the authentication methods that are supported
   130  type Auth struct {
   131  	ImagePullSecret string `json:"imagePullSecret,omitempty"`
   132  	// UserID          string `json:"userid,omitempty"`
   133  	// Password        string `json:"password,omitempty"`
   134  }
   135  
   136  // BuildPullSecret builds the pull secret string into the type expected by kubernetes
   137  func (a *Auth) BuildPullSecret() corev1.LocalObjectReference {
   138  	return corev1.LocalObjectReference{Name: a.ImagePullSecret}
   139  }
   140  
   141  // MountPath represent the configuration of volume mounts on a container
   142  type MountPath struct {
   143  	Name         string               `json:"name"`
   144  	Secret       string               `json:"secret"`
   145  	MountPath    string               `json:"mountpath"`
   146  	UsePVC       bool                 `json:"usePVC"`
   147  	SubPath      string               `json:"subpath,omitempty"`
   148  	Paths        []Path               `json:"paths,omitempty"`
   149  	VolumeSource *corev1.VolumeSource `json:"volumeSource,omitempty"`
   150  }
   151  
   152  type Path struct {
   153  	Key  string `json:"key"`
   154  	Path string `json:"path"`
   155  }
   156  
   157  // BuildVolumeMount builds the volume mount spec into the type expected by kubernetes
   158  func (m *MountPath) BuildVolumeMount() corev1.VolumeMount {
   159  	return corev1.VolumeMount{
   160  		Name:      m.Name,
   161  		MountPath: m.MountPath,
   162  		SubPath:   m.SubPath,
   163  	}
   164  }
   165  
   166  // BuildVolume builds the volume spec into the type expected by kubernetes
   167  func (m *MountPath) BuildVolume() corev1.Volume {
   168  	// In our initial HSM implementation, we made secrets as the default volume source and only
   169  	// allowed secrets based volumes. With the introducing of other HSM implementations (opencryptoki),
   170  	// other volume types had to be introduced and are now directly allowed in the configuration.
   171  	// However, to not break current users using older config this logic needs to persistent until
   172  	// we can deprecate older configs.
   173  	if m.VolumeSource == nil {
   174  		m.VolumeSource = &corev1.VolumeSource{
   175  			Secret: &corev1.SecretVolumeSource{
   176  				SecretName: m.Secret,
   177  			},
   178  		}
   179  	}
   180  
   181  	// Setting key/path is only supported for secrets, this is due to the fact
   182  	// that we made secrets as the default volume source and only allowed secrets based volumes.
   183  	// For other volume source types, they should configured directly in the hsm config.
   184  	for _, path := range m.Paths {
   185  		m.VolumeSource.Secret.Items = append(m.VolumeSource.Secret.Items,
   186  			corev1.KeyToPath{
   187  				Key:  path.Key,
   188  				Path: path.Path,
   189  			},
   190  		)
   191  	}
   192  
   193  	return corev1.Volume{
   194  		Name:         m.Name,
   195  		VolumeSource: *m.VolumeSource,
   196  	}
   197  }