diff --git a/contract/contract.go b/contract/contract.go index 5c3cfe3..447f1f8 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -60,31 +60,66 @@ func HpcrTgz(folderPath string) (string, error) { } // HpcrContractSignedEncrypted - function to generate Signed and Encrypted contract -func HpcrContractSignedEncrypted(contract, privateKey, encryptionCertificate string) (string, error) { - var contractMap map[string]interface{} - +func HpcrContractSignedEncrypted(contract, encryptionCertificate, privateKey string) (string, error) { if contract == "" || privateKey == "" { return "", fmt.Errorf("either contract or private key not parsed") } encryptCertificate := gen.FetchEncryptionCertificate(encryptionCertificate) - err := yaml.Unmarshal([]byte(contract), &contractMap) + publicKey, err := enc.GeneratePublicKey(privateKey) if err != nil { return "", err } - workloadData, err := gen.MapToYaml(contractMap["workload"].(map[string]interface{})) + signedEncryptContract, err := EncryptWrapper(contract, encryptCertificate, privateKey, publicKey) if err != nil { return "", err } - encryptedWorkload, _, err := Encrypter(workloadData, encryptCertificate) + return signedEncryptContract, nil +} + +// HpcrContractSignedEncryptedContractExpiry - function to generate sign with contract expiry enabled and encrypt contract (with CSR parameters and CSR file) +func HpcrContractSignedEncryptedContractExpiry(contract, encryptionCertificate, privateKey, cacert, caKey, csrDataStr, csrPemData string, expiryDays int) (string, error) { + if contract == "" || privateKey == "" || cacert == "" || caKey == "" { + return "", fmt.Errorf("required parameters missing") + } + + if csrPemData == "" && csrDataStr == "" || len(csrPemData) > 0 && len(csrDataStr) > 0 { + return "", fmt.Errorf("the CSR parameters and CSR PEM file are parsed together or both are nil") + } + + signingCert, err := enc.CreateSigningCert(privateKey, cacert, caKey, csrDataStr, csrPemData, expiryDays) if err != nil { return "", err } - publicKey, err := enc.GeneratePublicKey(privateKey) + finalContract, err := EncryptWrapper(contract, encryptionCertificate, privateKey, signingCert) + if err != nil { + return "", err + } + + return finalContract, nil +} + +// EncryptWrapper - wrapper function to sign (with and without contract expiry) and encrypt contract +func EncryptWrapper(contract, encryptionCertificate, privateKey, publicKey string) (string, error) { + var contractMap map[string]interface{} + + encryptCertificate := gen.FetchEncryptionCertificate(encryptionCertificate) + + err := yaml.Unmarshal([]byte(contract), &contractMap) + if err != nil { + return "", err + } + + workloadData, err := gen.MapToYaml(contractMap["workload"].(map[string]interface{})) + if err != nil { + return "", err + } + + encryptedWorkload, _, err := Encrypter(workloadData, encryptCertificate) if err != nil { return "", err } diff --git a/contract/contract_test.go b/contract/contract_test.go index 4a5b3bd..186bfa7 100644 --- a/contract/contract_test.go +++ b/contract/contract_test.go @@ -1,15 +1,13 @@ package contract import ( + "encoding/json" "fmt" "io" "os" "testing" "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" - - gen "github.com/Sashwat-K/lib-hpcr/common/general" ) const ( @@ -29,8 +27,108 @@ const ( simpleContractPath = "../samples/simple_contract.yaml" samplePrivateKeyPath = "../samples/encrypt/private.pem" + samplePublicKeyPath = "../samples/encrypt/public.pem" + + sampleCePrivateKeyPath = "../samples/contract-expiry/private.pem" + sampleCeCaCertPath = "../samples/contract-expiry/personal_ca.crt" + sampleCeCaKeyPath = "../samples/contract-expiry/personal_ca.pem" + sampleCeCsrPath = "../samples/contract-expiry/csr.pem" + sampleContractExpiryDays = 365 +) + +var ( + sampleCeCSRPems = map[string]interface{}{ + "country": "IN", + "state": "Karnataka", + "location": "Bangalore", + "org": "IBM", + "unit": "ISDL", + "domain": "HPVS", + "mail": "sashwat.k@ibm.com", + } ) +// common - common function to pull data from files +func common(testType string) (string, string, string, string, string, error) { + simpleContractFile, err := os.Open(simpleContractPath) + if err != nil { + return "", "", "", "", "", err + } + defer simpleContractFile.Close() + + contract, err := io.ReadAll(simpleContractFile) + if err != nil { + return "", "", "", "", "", err + } + + privateKeyFile, err := os.Open(samplePrivateKeyPath) + if err != nil { + return "", "", "", "", "", err + } + defer privateKeyFile.Close() + + privateKey, err := io.ReadAll(privateKeyFile) + if err != nil { + return "", "", "", "", "", err + } + + if testType == "TestHpcrContractSignedEncrypted" { + return string(contract), string(privateKey), "", "", "", nil + } else if testType == "TestEncryptWrapper" { + publicKeyFile, err := os.Open(samplePublicKeyPath) + if err != nil { + return "", "", "", "", "", err + } + defer privateKeyFile.Close() + + publicKey, err := io.ReadAll(publicKeyFile) + if err != nil { + return "", "", "", "", "", err + } + return string(contract), string(privateKey), string(publicKey), "", "", nil + } else if testType == "TestHpcrContractSignedEncryptedContractExpiryCsrParams" || testType == "TestHpcrContractSignedEncryptedContractExpiryCsrPem" { + cePrivateKeyPath, err := os.Open(sampleCePrivateKeyPath) + if err != nil { + return "", "", "", "", "", err + } + defer cePrivateKeyPath.Close() + + cePrivateKey, err := io.ReadAll(cePrivateKeyPath) + if err != nil { + return "", "", "", "", "", err + } + + caCertPath, err := os.Open(sampleCeCaCertPath) + if err != nil { + fmt.Println("Error parsing CA certificate - ", err) + return "", "", "", "", "", err + } + defer caCertPath.Close() + + caCert, err := io.ReadAll(caCertPath) + if err != nil { + fmt.Println(err) + return "", "", "", "", "", err + } + + caKeyPath, err := os.Open(sampleCeCaKeyPath) + if err != nil { + fmt.Println("Error parsing CA certificate - ", err) + return "", "", "", "", "", err + } + defer caCertPath.Close() + + caKey, err := io.ReadAll(caKeyPath) + if err != nil { + fmt.Println(err) + return "", "", "", "", "", err + } + + return string(contract), string(cePrivateKey), "", string(caCert), string(caKey), err + } + return "", "", "", "", "", err +} + // Testcase to check if TestHpcrText() is able to encode text and generate SHA256 func TestHpcrText(t *testing.T) { base64, sha256, err := HpcrText(sampleStringData) @@ -88,41 +186,77 @@ func TestHpcrTgz(t *testing.T) { // Testcase to check if HpcrContractSignedEncrypted() is able to generate func TestHpcrContractSignedEncrypted(t *testing.T) { - var contractMap map[string]interface{} - file, err := os.Open(simpleContractPath) + contract, privateKey, _, _, _, err := common("TestHpcrContractSignedEncrypted") if err != nil { fmt.Println(err) } - defer file.Close() - contract, err := io.ReadAll(file) + result, err := HpcrContractSignedEncrypted(contract, "", privateKey) if err != nil { fmt.Println(err) } - err = yaml.Unmarshal([]byte(contract), &contractMap) + assert.NotEmpty(t, result) + assert.NoError(t, err) +} + +// Testcase to check if HpcrContractSignedEncryptedContractExpiry() is able to create signed and encrypted contract with contract expiry enabled with CSR parameters +func TestHpcrContractSignedEncryptedContractExpiryCsrParams(t *testing.T) { + contract, privateKey, _, caCert, caKey, err := common("TestHpcrContractSignedEncryptedContractExpiryCsrParams") if err != nil { fmt.Println(err) } - privateKeyFile, err := os.Open(samplePrivateKeyPath) + csrParams, err := json.Marshal(sampleCeCSRPems) if err != nil { fmt.Println(err) } - defer privateKeyFile.Close() - privateKey, err := io.ReadAll(privateKeyFile) + result, err := HpcrContractSignedEncryptedContractExpiry(contract, "", privateKey, caCert, caKey, string(csrParams), "", sampleContractExpiryDays) + if err != nil { + fmt.Println(err) + } + + assert.NotEmpty(t, result) + assert.NoError(t, err) +} + +// Testcase to check if HpcrContractSignedEncryptedContractExpiry() is able to create signed and encrypted contract with contract expiry enabled with CSR PEM data +func TestHpcrContractSignedEncryptedContractExpiryCsrPem(t *testing.T) { + contract, privateKey, _, caCert, caKey, err := common("TestHpcrContractSignedEncryptedContractExpiryCsrPem") if err != nil { fmt.Println(err) } - contractStr, err := gen.MapToYaml(contractMap) + csrPemFile, err := os.Open(sampleCeCsrPath) + if err != nil { + fmt.Println("Error parsing CSR - ", err) + } + defer csrPemFile.Close() + + csr, err := io.ReadAll(csrPemFile) + if err != nil { + fmt.Println(err) + } + + result, err := HpcrContractSignedEncryptedContractExpiry(contract, "", privateKey, caCert, caKey, "", string(csr), sampleContractExpiryDays) + if err != nil { + fmt.Println(err) + } + + assert.NotEmpty(t, result) + assert.NoError(t, err) +} + +// Testcase to check if EncryptWrapper() is able to sign and encrypt a contract +func TestEncryptWrapper(t *testing.T) { + contract, privateKey, publicKey, _, _, err := common("TestEncryptWrapper") if err != nil { fmt.Println(err) } - result, err := HpcrContractSignedEncrypted(contractStr, string(privateKey), "") + result, err := EncryptWrapper(contract, "", privateKey, publicKey) if err != nil { fmt.Println(err) }