Skip to content

Commit

Permalink
feat: add crypto utils, template functions and ibm vpc certificate
Browse files Browse the repository at this point in the history
Signed-off-by: Mehant Kammakomati <kmehant@gmail.com>
  • Loading branch information
kmehant committed Sep 16, 2022
1 parent 5064d5f commit 4413093
Show file tree
Hide file tree
Showing 10 changed files with 463 additions and 1 deletion.
4 changes: 4 additions & 0 deletions assets/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ var AssetsDir embed.FS
//AssetFilePermissions is embedded file having permissions information for the assets
//go:embed filepermissions.yaml
var AssetFilePermissions string

//IbmHyperProtectCert is embedded file having IBM Hyper Protect encryption certificate
//go:embed ibm-hyper-protect-container-runtime-1-0-s390x-4-encrypt.crt
var IbmHyperProtectCert string
34 changes: 34 additions & 0 deletions assets/ibm-hyper-protect-container-runtime-1-0-s390x-4-encrypt.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF8TCCA9mgAwIBAgIQLKNAizePV1jGkvBknjjfOzANBgkqhkiG9w0BAQ0FADCB
0TELMAkGA1UEBhMCREUxGzAZBgNVBAgMEkJhZGVuLVfDvHJ0dGVtYmVyZzETMBEG
A1UEBwwKQsO2YmxpbmdlbjE0MDIGA1UECgwrSUJNIERldXRzY2hsYW5kIFJlc2Vh
cmNoICYgRGV2ZWxvcG1lbnQgR21iSDEkMCIGA1UECxMbSUJNIFogSHlicmlkIENs
b3VkIFBsYXRmb3JtMTQwMgYDVQQDDCtJQk0gRGV1dHNjaGxhbmQgUmVzZWFyY2gg
JiBEZXZlbG9wbWVudCBHbWJIMB4XDTIyMDkwMjE2NTc0N1oXDTQyMDkwMjE2NTc1
N1owgZYxCzAJBgNVBAYTAkRFMQswCQYDVQQIEwJCVzETMBEGA1UEBxMKQm9lYmxp
bmdlbjEhMB8GA1UECgwYSUJNIERldXRzY2hsYW5kIFImRCBHbWJIMSQwIgYDVQQL
ExtJQk0gWiBIeWJyaWQgQ2xvdWQgUGxhdGZvcm0xHDAaBgNVBAMTE2NvbnRyYWN0
LWRlY3J5cHRpb24wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDI9Jx9
NXPsbONFVqIsXfzB/4WI4Kj070AxveF8QHTMb8mQ8KOD5ZDs6Ug1fli2JbxFPfvK
oFD0v1FNsxBhjWHAkq8LpeIzrG0YVLmDcjQqEaJQd58YK8GygOLy7qoRMedsVr2X
+MIqxJda06tc/O3GrM4swZRQVh7I0BHB9cJ3mLbh7St3vmhBpNZt9EKIgTJUGFUH
gTpeZuh2AjOcKsdrbzfGcs+4q1CstVNZ9eECVc27JPAzzrfzS8ZRlLJPOVEVDj1Z
gs3rA36eTxRMC0XuJC+mgKASJsFKygYQmfbs1mzIN0oIzsewjHM6AywuJ21Srjaq
gMSaRKzfpnMELJqWpIKFDGjj+p6anp8zJPYQy9IrOG8ifgCg+LhVGQ6mx3xMgY3m
H9Mwcto/ox6mkLf/7JYWK2RoAZEJRuojuMpOfeOLEkkzkBgzgD2JLh2ps+Zc7YxE
I9O02vMHUHhamqLyjD1OOBUBbYQ+W+28svbMgr3m5F8ILzXVWTnT6+h6WStXhLbk
zUIsAWconRt6g3A6Y9UCeK252j3ITjKPlcduICZkkcnaj73VDACRmoOVBPrnb2Ex
YfXhibBlwPcGyUV+GwlZgs5IN+X8GIU0I6QFFUUh3+BhgbVu8Rei0CKl52aRyFTe
w9wo0abntwYLQlovZLNsPtMeZIGO/P37IMelGwIDAQABMA0GCSqGSIb3DQEBDQUA
A4ICAQAgBhbamlqQlOYNgyOOPnuDNRe/LEshv+yeHS5Yqjgb/o5WzhHQNla6kQpD
TgbYvF70Qkj3agSH6+M6C+mmdgzGNQOWhnPBPtDiySOn8BvlhIvcsOz/OQyIi0Se
4vqiKPQmGUJ9aZCmzmkKbzUIpWJZy8XOcG15a5lW1OIDIVl7qRehZDQ0MqhYk5yQ
hXG/0o50APhSJ3fN6ulcdP/BfMGQmHs3fRHiaOMxJvJC/obUSDCgDIrBodAk2GvW
8aKEu2yRS1RoespumrkB621eULWhTQ//M31JlvBSo5daulOcjfBeCmGcQGQFJs45
hsTkLfltYf6nkFxzrjPvaRMT9xGmXFUkMrr163P2f0ngDp2BopqAGaVT/yD4llOs
Li5o5ZEcSOhILypa141pGwDBK/7IGv35zicO39VlpKsF/sRej4xPMkZOSlBSAgQf
oDJ6NLx69TtmcDpz0nU9y4yjZQDWj2CiG8yK5Lr9ayq8ayOneJr3Krh0bJ43izD2
19UeNHaQrN94ylMNAyNB+2QrOtkAYuu0XKYuEDYaKx5V9w0Oodc2RJVZVt4PeHyY
BxB0v4gNdfr/ESjrmwHfQJh1wQYMG6mUUHseIGKwb7qLaHIp7Nxxc1bydlxEHqqB
bF0c1daNoz1JrAL6rrhMRMT8TQZTw+n/+R3HDbdIWG9alxtNbg==
-----END CERTIFICATE-----
139 changes: 139 additions & 0 deletions common/cryptoutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright IBM Corporation 2021
*
* 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.
*/

package common

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"

"github.com/konveyor/move2kube/assets"

"github.com/sirupsen/logrus"
"golang.org/x/crypto/pbkdf2"
)

// RsaCertEncryptWrapper can be used to encrypt the data using RSA PKCS1v15 algorithm with certificate as key
func RsaCertEncryptWrapper(certificate string, data string) string {
if certificate == "" {
logrus.Info("using certificate from IBM Hyper Protect Container Runtime")
certificate = assets.IbmHyperProtectCert
}

rsaPublicKey, err := getRSAPublicKeyFromCertificate([]byte(certificate))
if err != nil {
logrus.Errorf("failed to parse the certificate and get the RSA public key from it. Error: %q", err)
}

out, err := rsaEncrypt(rsaPublicKey, []byte(data))
if err != nil {
logrus.Errorf("failed to encrypt the data with RSA PKCS1v15 algorithm with certificate as key : %q", err)
}

return string(out)
}

// AesCbcEncryptWithPbkdfWrapper can be used to encrypt the data using AES 256 CBC mode with Pbkdf key derivation
func AesCbcEncryptWithPbkdfWrapper(key string, data string) string {
salt := make([]byte, 16)
_, err := rand.Read(salt)
if err != nil {
logrus.Errorf("failed to prepare the salt : %s", err)
}
out, err := aesCbcEncryptWithPbkdf([]byte(key), salt, []byte(data))
if err != nil {
logrus.Errorf("failed to encrypt the data using AES 256 CBC mode with Pbkdf key derivation : %q", err)
}
opensslOut := toOpenSSLFormat(salt, out)
return string(opensslOut)
}

// getRSAPublicKeyFromCertificate gets a RSA public key from a PEM-encoded certificate.crt file.
func getRSAPublicKeyFromCertificate(certificateInPemFormat []byte) (*rsa.PublicKey, error) {
block, _ := pem.Decode(certificateInPemFormat)
if block == nil {
return nil, fmt.Errorf("invalid certificate. Expected a PEM encoded certificate")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse the x509 certificate. Error: %q", err)
}
pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("failed to type cast the public key from the x509 certificate. Actual type: %T and value: %+v", cert.PublicKey, cert.PublicKey)
}
return pubKey, nil
}

// rsaEncrypt encrypts the plain text using the RSA public key.
func rsaEncrypt(publicKey *rsa.PublicKey, plainText []byte) ([]byte, error) {
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
if err != nil {
return cipherText, fmt.Errorf("failed to RSA encrypt the plain text. Error: %q", err)
}
return cipherText, nil
}

// deriveAesKeyAndIv returns an AES key and IV derived from the password and salt using PBKDF2 function.
func deriveAesKeyAndIv(password, salt []byte) ([]byte, []byte) {
aesKeyAndIv := pbkdf2.Key(password, salt, 10000, 32+16, sha256.New)
return aesKeyAndIv[:32], aesKeyAndIv[32:]
}

// aesCbcEncryptWithPbkdf derives an AES key and IV using the given password and salt and then encrypts the plain text.
func aesCbcEncryptWithPbkdf(password, salt, plainText []byte) ([]byte, error) {

// derive an AES key and IV using the password and the salt

aesKey, iv := deriveAesKeyAndIv(password, salt)

// encrypt the workload using the AES key

aesCipher, err := aes.NewCipher(aesKey)
if err != nil {
return nil, fmt.Errorf("failed to create a new AES cipher using the key. Error: %q", err)
}

// pad the plain text as per PKCS#5 https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS#5_and_PKCS#7

paddingRequired := aes.BlockSize - len(plainText)%aes.BlockSize
if paddingRequired == 0 {
paddingRequired = aes.BlockSize
}
padding := make([]byte, paddingRequired)
for i := 0; i < paddingRequired; i++ {
padding[i] = byte(paddingRequired)
}

paddedPlainText := append(plainText, padding...)
cipherText := make([]byte, len(paddedPlainText))

aesCbcEncrypter := cipher.NewCBCEncrypter(aesCipher, iv)
aesCbcEncrypter.CryptBlocks(cipherText, paddedPlainText)
return cipherText, nil
}

// toOpenSSLFormat converts the cipher text to OpenSSL encrypted with password and salt format.
// http://justsolve.archiveteam.org/wiki/OpenSSL_salted_format
func toOpenSSLFormat(salt, cipherText []byte) []byte {
return append(append([]byte("Salted__"), salt...), cipherText...)
}
13 changes: 13 additions & 0 deletions customizations/custom-vpc-contract-generator/templates/env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: env
logging:
logDNA:
hostname: {{ .LogHostName }}
ingestionKey: {{ .IngestionKey }}
port: {{ .LogPort }}
volumes:
{{- range $k, $v := .EnvVolumes}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{{- define "envTemplate"}}type: env
logging:
logDNA:
hostname: {{ .LogHostName }}
ingestionKey: {{ .IngestionKey }}
port: {{ .LogPort }}
volumes:
{{- range $k, $v := .EnvVolumes}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
{{- end}}
{{- define "workloadTemplate"}}type: workload
auths:
{{- range $k, $v := .Auths}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
compose:
archive: {{ .ComposeArchive }}
images:
dct:
{{- range $k, $v := .Images}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
volumes:
{{- range $k, $v := .WorkloadVolumes}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
env:
{{- range $vk, $vv := .WorkloadEnvs}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}{{- if .EnvPass}}env: "hyper-protect-basic.{{rsaCertEnc "" .EnvPass | b64enc}}.
{{- $envData := execTpl "envTemplate" .}}
{{- aesCbcPbkdfEnc .EnvPass $envData | b64enc}}"
{{- end}}
{{- if .WorkloadPass}}
workload: "hyper-protect-basic.{{rsaCertEnc "" .WorkloadPass | b64enc}}.
{{- $workloadData := execTpl "workloadTemplate" .}}
{{- aesCbcPbkdfEnc .WorkloadPass $workloadData | b64enc}}"
{{- end}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{{- if .EnvType}}env: |
type: env
logging:
logDNA:
hostname: {{ .LogHostName }}
ingestionKey: {{ .IngestionKey }}
port: {{ .LogPort }}
volumes:
{{- range $k, $v := .EnvVolumes}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
{{- end}}
{{- if .WorkloadType}}
workload: |
type: workload
auths:
{{- range $k, $v := .Auths}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
compose:
archive: {{ .ComposeArchive }}
images:
dct:
{{- range $k, $v := .Images}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
volumes:
{{- range $k, $v := .WorkloadVolumes}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
env:
{{- range $vk, $vv := .WorkloadEnvs}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
type: workload
auths:
{{- range $k, $v := .Auths}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
compose:
archive: {{ .ComposeArchive }}
images:
dct:
{{- range $k, $v := .Images}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
volumes:
{{- range $k, $v := .WorkloadVolumes}}
{{$k}}:
{{- range $vk, $vv := $v}}
{{$vk}}: {{$vv}}
{{- end}}
{{- end}}
env:
{{- range $vk, $vv := .WorkloadEnvs}}
{{$vk}}: {{$vv}}
{{- end}}
14 changes: 14 additions & 0 deletions customizations/custom-vpc-contract-generator/transformer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: move2kube.konveyor.io/v1alpha1
kind: Transformer
metadata:
name: VpcContractGenerator
labels:
move2kube.konveyor.io/built-in: false
spec:
class: "Starlark"
directoryDetect:
levels: 0
config:
starFile: "vpccontractgenerator.star"
invokedByDefault:
enabled: true
Loading

0 comments on commit 4413093

Please sign in to comment.