github.com/SAP/jenkins-library@v1.362.0/cmd/writePipelineEnv.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/sha256"
     8  	b64 "encoding/base64"
     9  	"encoding/json"
    10  	"fmt"
    11  	"github.com/SAP/jenkins-library/pkg/config"
    12  	"io"
    13  	"os"
    14  	"path/filepath"
    15  
    16  	"github.com/SAP/jenkins-library/pkg/log"
    17  	"github.com/SAP/jenkins-library/pkg/piperenv"
    18  	"github.com/spf13/cobra"
    19  )
    20  
    21  // WritePipelineEnv Serializes the commonPipelineEnvironment JSON to disk
    22  func WritePipelineEnv() *cobra.Command {
    23  	var stepConfig artifactPrepareVersionOptions
    24  	var encryptedCPE bool
    25  	metadata := artifactPrepareVersionMetadata()
    26  
    27  	writePipelineEnv := &cobra.Command{
    28  		Use:   "writePipelineEnv",
    29  		Short: "Serializes the commonPipelineEnvironment JSON to disk",
    30  		PreRun: func(cmd *cobra.Command, args []string) {
    31  			path, _ := os.Getwd()
    32  			fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
    33  			log.RegisterHook(fatalHook)
    34  
    35  			err := PrepareConfig(cmd, &metadata, "", &stepConfig, config.OpenPiperFile)
    36  			if err != nil {
    37  				log.SetErrorCategory(log.ErrorConfiguration)
    38  				return
    39  			}
    40  			log.RegisterSecret(stepConfig.Password)
    41  			log.RegisterSecret(stepConfig.Username)
    42  		},
    43  
    44  		Run: func(cmd *cobra.Command, args []string) {
    45  			err := runWritePipelineEnv(stepConfig.Password, encryptedCPE)
    46  			if err != nil {
    47  				log.Entry().Fatalf("error when writing common Pipeline environment: %v", err)
    48  			}
    49  		},
    50  	}
    51  
    52  	writePipelineEnv.Flags().BoolVar(&encryptedCPE, "encryptedCPE", false, "Bool to use encryption in CPE")
    53  	return writePipelineEnv
    54  }
    55  
    56  func runWritePipelineEnv(stepConfigPassword string, encryptedCPE bool) error {
    57  	var err error
    58  	pipelineEnv, ok := os.LookupEnv("PIPER_pipelineEnv")
    59  	inBytes := []byte(pipelineEnv)
    60  	if !ok {
    61  		var err error
    62  		inBytes, err = io.ReadAll(os.Stdin)
    63  		if err != nil {
    64  			return err
    65  		}
    66  	}
    67  	if len(inBytes) == 0 {
    68  		return nil
    69  	}
    70  
    71  	// try to decrypt
    72  	if encryptedCPE {
    73  		log.Entry().Debug("trying to decrypt CPE")
    74  		if stepConfigPassword == "" {
    75  			return fmt.Errorf("empty stepConfigPassword")
    76  		}
    77  
    78  		inBytes, err = decrypt([]byte(stepConfigPassword), inBytes)
    79  		if err != nil {
    80  			log.Entry().Fatal(err)
    81  		}
    82  	}
    83  
    84  	commonPipelineEnv := piperenv.CPEMap{}
    85  	decoder := json.NewDecoder(bytes.NewReader(inBytes))
    86  	decoder.UseNumber()
    87  	err = decoder.Decode(&commonPipelineEnv)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	rootPath := filepath.Join(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
    93  	err = commonPipelineEnv.WriteToDisk(rootPath)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	writtenBytes, err := json.MarshalIndent(commonPipelineEnv, "", "\t")
    99  	if err != nil {
   100  		return err
   101  	}
   102  	_, err = os.Stdout.Write(writtenBytes)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	return nil
   107  }
   108  
   109  func decrypt(secret, base64CipherText []byte) ([]byte, error) {
   110  	// decode from base64
   111  	cipherText, err := b64.StdEncoding.DecodeString(string(base64CipherText))
   112  	if err != nil {
   113  		return nil, fmt.Errorf("failed to decode from base64: %v", err)
   114  	}
   115  
   116  	// use SHA256 as key
   117  	key := sha256.Sum256(secret)
   118  	block, err := aes.NewCipher(key[:])
   119  	if err != nil {
   120  		return nil, fmt.Errorf("failed to create new cipher: %v", err)
   121  	}
   122  
   123  	if len(cipherText) < aes.BlockSize {
   124  		return nil, fmt.Errorf("invalid ciphertext block size")
   125  	}
   126  
   127  	iv := cipherText[:aes.BlockSize]
   128  	cipherText = cipherText[aes.BlockSize:]
   129  
   130  	stream := cipher.NewCFBDecrypter(block, iv)
   131  	stream.XORKeyStream(cipherText, cipherText)
   132  
   133  	return cipherText, nil
   134  }