github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/accesscontrol/attributes/attributes_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package attributes
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/x509"
    22  	"encoding/pem"
    23  	"fmt"
    24  
    25  	"io/ioutil"
    26  	"os"
    27  	"strings"
    28  	"testing"
    29  
    30  	"github.com/golang/protobuf/proto"
    31  	pb "github.com/hyperledger/fabric/accesscontrol/attributes/proto"
    32  	"github.com/hyperledger/fabric/core/crypto/primitives"
    33  )
    34  
    35  func TestMain(m *testing.M) {
    36  	if err := primitives.InitSecurityLevel("SHA3", 256); err != nil {
    37  		fmt.Printf("Failed setting security level: %v", err)
    38  	}
    39  
    40  	ret := m.Run()
    41  	os.Exit(ret)
    42  }
    43  
    44  func TestEncryptDecryptAttributeValuePK0(t *testing.T) {
    45  	expected := "ACompany"
    46  
    47  	preK0 := []byte{
    48  		91, 206, 163, 104, 247, 74, 149, 209, 91, 137, 215, 236,
    49  		84, 135, 9, 70, 160, 138, 89, 163, 240, 223, 83, 164, 58,
    50  		208, 199, 23, 221, 123, 53, 220, 15, 41, 28, 111, 166,
    51  		28, 29, 187, 97, 229, 117, 117, 49, 192, 134, 31, 151}
    52  
    53  	encryptedAttribute, err := EncryptAttributeValuePK0(preK0, "company", []byte(expected))
    54  	if err != nil {
    55  		t.Error(err)
    56  	}
    57  
    58  	attributeKey := getAttributeKey(preK0, "company")
    59  
    60  	attribute, err := DecryptAttributeValue(attributeKey, encryptedAttribute)
    61  	if err != nil {
    62  		t.Error(err)
    63  	}
    64  
    65  	if string(attribute) != expected {
    66  		t.Errorf("Failed decrypting attribute. Expected: %v, Actual: %v", expected, attribute)
    67  	}
    68  }
    69  
    70  func TestGetKAndValueForAttribute(t *testing.T) {
    71  	expected := "Software Engineer"
    72  
    73  	tcert, prek0, err := loadTCertAndPreK0()
    74  	if err != nil {
    75  		t.Error(err)
    76  	}
    77  
    78  	_, attribute, err := getKAndValueForAttribute("position", prek0, tcert)
    79  	if err != nil {
    80  		t.Error(err)
    81  	}
    82  
    83  	if string(attribute) != expected {
    84  		t.Errorf("Failed retrieving attribute value from TCert. Expected: %v, Actual: %v", expected, string(attribute))
    85  	}
    86  }
    87  
    88  func TestGetKAndValueForAttribute_MissingAttribute(t *testing.T) {
    89  	tcert, prek0, err := loadTCertAndPreK0()
    90  	if err != nil {
    91  		t.Error(err)
    92  	}
    93  
    94  	_, _, err = getKAndValueForAttribute("business_unit", prek0, tcert)
    95  	if err == nil {
    96  		t.Errorf("Trying to read an attribute that is not part of the TCert should produce an error")
    97  	}
    98  }
    99  
   100  func TestGetValueForAttribute(t *testing.T) {
   101  	expected := "Software Engineer"
   102  
   103  	tcert, prek0, err := loadTCertAndPreK0()
   104  	if err != nil {
   105  		t.Error(err)
   106  	}
   107  
   108  	value, err := GetValueForAttribute("position", prek0, tcert)
   109  	if err != nil {
   110  		t.Error(err)
   111  	}
   112  
   113  	if string(value) != expected {
   114  		t.Errorf("Failed retrieving attribute value from TCert. Expected: %v, Actual: %v", expected, string(value))
   115  	}
   116  }
   117  
   118  func TestGetValueForAttribute_MissingAttribute(t *testing.T) {
   119  	tcert, prek0, err := loadTCertAndPreK0()
   120  	if err != nil {
   121  		t.Error(err)
   122  	}
   123  
   124  	_, err = GetValueForAttribute("business_unit", prek0, tcert)
   125  	if err == nil {
   126  		t.Errorf("Trying to read an attribute that is not part of the TCert should produce an error")
   127  	}
   128  }
   129  
   130  func TestGetKForAttribute(t *testing.T) {
   131  	expected := "Software Engineer"
   132  
   133  	tcert, prek0, err := loadTCertAndPreK0()
   134  	if err != nil {
   135  		t.Error(err)
   136  	}
   137  
   138  	key, err := GetKForAttribute("position", prek0, tcert)
   139  	if err != nil {
   140  		t.Error(err)
   141  	}
   142  
   143  	encryptedValue, err := EncryptAttributeValuePK0(prek0, "position", []byte(expected))
   144  	if err != nil {
   145  		t.Error(err)
   146  	}
   147  
   148  	decryptedValue, err := DecryptAttributeValue(key, encryptedValue)
   149  	if err != nil {
   150  		t.Error(err)
   151  	}
   152  
   153  	if string(decryptedValue) != expected {
   154  		t.Errorf("Failed decrypting attribute used calculated key. Expected: %v, Actual: %v", expected, string(decryptedValue))
   155  	}
   156  }
   157  
   158  func TestGetKForAttribute_MissingAttribute(t *testing.T) {
   159  	tcert, prek0, err := loadTCertAndPreK0()
   160  	if err != nil {
   161  		t.Error(err)
   162  	}
   163  
   164  	_, err = GetKForAttribute("business_unit", prek0, tcert)
   165  	if err == nil {
   166  		t.Errorf("Trying to get a key for an attribute that is not part of the TCert should produce an error")
   167  	}
   168  }
   169  
   170  func TestParseEmptyAttributesHeader(t *testing.T) {
   171  	_, err := ParseAttributesHeader("")
   172  	if err == nil {
   173  		t.Error("Empty header should produce a parsing error")
   174  	}
   175  }
   176  
   177  func TestParseAttributesHeader_NotNumberPosition(t *testing.T) {
   178  	_, err := ParseAttributesHeader(headerPrefix + "position->a#")
   179  	if err == nil {
   180  		t.Error("Not number position in the header should produce a parsing error")
   181  	}
   182  }
   183  
   184  func TestBuildAndParseAttributesHeader(t *testing.T) {
   185  	attributes := make(map[string]int)
   186  	attributes["company"] = 1
   187  	attributes["position"] = 2
   188  
   189  	headerRaw, err := BuildAttributesHeader(attributes)
   190  	if err != nil {
   191  		t.Error(err)
   192  	}
   193  	header := string(headerRaw[:])
   194  
   195  	components, err := ParseAttributesHeader(header)
   196  	if err != nil {
   197  		t.Error(err)
   198  	}
   199  
   200  	if len(components) != 2 {
   201  		t.Errorf("Error parsing header. Expecting two entries in header, found %v instead", len(components))
   202  	}
   203  
   204  	if components["company"] != 1 {
   205  		t.Errorf("Error parsing header. Expected %v with value %v, found %v instead", "company", 1, components["company"])
   206  	}
   207  
   208  	if components["position"] != 2 {
   209  		t.Errorf("Error parsing header. Expected %v with value %v, found %v instead", "position", 2, components["position"])
   210  	}
   211  }
   212  
   213  func TestReadAttributeHeader(t *testing.T) {
   214  	tcert, prek0, err := loadTCertAndPreK0()
   215  	if err != nil {
   216  		t.Error(err)
   217  	}
   218  
   219  	headerKey := getAttributeKey(prek0, HeaderAttributeName)
   220  
   221  	header, encrypted, err := ReadAttributeHeader(tcert, headerKey)
   222  
   223  	if err != nil {
   224  		t.Error(err)
   225  	}
   226  
   227  	if !encrypted {
   228  		t.Errorf("Error parsing header. Expecting encrypted header.")
   229  	}
   230  
   231  	if len(header) != 1 {
   232  		t.Errorf("Error parsing header. Expecting %v entries in header, found %v instead", 1, len(header))
   233  	}
   234  
   235  	if header["position"] != 1 {
   236  		t.Errorf("Error parsing header. Expected %v with value %v, found %v instead", "position", 1, header["position"])
   237  	}
   238  }
   239  
   240  func TestReadAttributeHeader_WithoutHeaderKey(t *testing.T) {
   241  	tcert, _, err := loadTCertAndPreK0()
   242  	if err != nil {
   243  		t.Error(err)
   244  	}
   245  
   246  	_, _, err = ReadAttributeHeader(tcert, nil)
   247  
   248  	if err == nil {
   249  		t.Error(err)
   250  	}
   251  }
   252  
   253  func TestReadAttributeHeader_InvalidHeaderKey(t *testing.T) {
   254  	tcert, prek0, err := loadTCertAndPreK0()
   255  	if err != nil {
   256  		t.Error(err)
   257  	}
   258  
   259  	headerKey := getAttributeKey(prek0, HeaderAttributeName+"_invalid")
   260  
   261  	_, _, err = ReadAttributeHeader(tcert, headerKey)
   262  
   263  	if err == nil {
   264  		t.Error(err)
   265  	}
   266  }
   267  
   268  func TestReadTCertAttributeByPosition(t *testing.T) {
   269  	expected := "Software Engineer"
   270  
   271  	tcert, prek0, err := loadTCertAndPreK0()
   272  	if err != nil {
   273  		t.Error(err)
   274  	}
   275  
   276  	encryptedAttribute, err := ReadTCertAttributeByPosition(tcert, 1)
   277  
   278  	if err != nil {
   279  		t.Error(err)
   280  	}
   281  
   282  	attributeKey := getAttributeKey(prek0, "position")
   283  
   284  	attribute, err := DecryptAttributeValue(attributeKey, encryptedAttribute)
   285  
   286  	if err != nil {
   287  		t.Error(err)
   288  	}
   289  
   290  	if string(attribute) != expected {
   291  		t.Errorf("Failed retrieving attribute value from TCert. Expected: %v, Actual: %v", expected, string(attribute))
   292  	}
   293  }
   294  
   295  func TestGetAttributesMetadata(t *testing.T) {
   296  	metadata := []byte{255, 255, 255, 255}
   297  	entries := make([]*pb.AttributesMetadataEntry, 1)
   298  	var entry pb.AttributesMetadataEntry
   299  	entry.AttributeName = "position"
   300  	entry.AttributeKey = []byte{0, 0, 0, 0}
   301  	entries[0] = &entry
   302  	attributesMetadata := pb.AttributesMetadata{Metadata: metadata, Entries: entries}
   303  	raw, err := proto.Marshal(&attributesMetadata)
   304  	if err != nil {
   305  		t.Error(err)
   306  	}
   307  	resultMetadata, err := GetAttributesMetadata(raw)
   308  	if err != nil {
   309  		t.Error(err)
   310  	}
   311  	if bytes.Compare(resultMetadata.Metadata, attributesMetadata.Metadata) != 0 {
   312  		t.Fatalf("Invalid metadata expected %v result %v", attributesMetadata.Metadata, resultMetadata.Metadata)
   313  	}
   314  	if resultMetadata.Entries[0].AttributeName != attributesMetadata.Entries[0].AttributeName {
   315  		t.Fatalf("Invalid first entry attribute name expected %v result %v", attributesMetadata.Entries[0].AttributeName, resultMetadata.Entries[0].AttributeName)
   316  	}
   317  	if bytes.Compare(resultMetadata.Entries[0].AttributeKey, attributesMetadata.Entries[0].AttributeKey) != 0 {
   318  		t.Fatalf("Invalid first entry attribute key expected %v result %v", attributesMetadata.Entries[0].AttributeKey, resultMetadata.Entries[0].AttributeKey)
   319  	}
   320  }
   321  
   322  func TestReadTCertAttributeByPosition_InvalidPositions(t *testing.T) {
   323  	tcert, _, err := loadTCertAndPreK0()
   324  	if err != nil {
   325  		t.Error(err)
   326  	}
   327  
   328  	_, err = ReadTCertAttributeByPosition(tcert, 2)
   329  
   330  	if err == nil {
   331  		t.Error("Test should have failed since there is no attribute in the position 2 of the TCert")
   332  	}
   333  
   334  	_, err = ReadTCertAttributeByPosition(tcert, -2)
   335  
   336  	if err == nil {
   337  		t.Error("Test should have failed since attribute positions should be positive integer values")
   338  	}
   339  }
   340  
   341  func TestCreateAttributesMetadataObjectFromCert(t *testing.T) {
   342  	tcert, preK0, err := loadTCertAndPreK0()
   343  	if err != nil {
   344  		t.Error(err)
   345  	}
   346  
   347  	metadata := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
   348  	attributeKeys := []string{"position"}
   349  	metadataObj := CreateAttributesMetadataObjectFromCert(tcert, metadata, preK0, attributeKeys)
   350  	if bytes.Compare(metadataObj.Metadata, metadata) != 0 {
   351  		t.Errorf("Invalid metadata result %v but expected %v", metadataObj.Metadata, metadata)
   352  	}
   353  
   354  	entries := metadataObj.GetEntries()
   355  	if len(entries) != 2 {
   356  		t.Errorf("Invalid entries in metadata result %v but expected %v", len(entries), 3)
   357  	}
   358  
   359  	firstEntry := entries[0]
   360  	if firstEntry.AttributeName != "position" {
   361  		t.Errorf("Invalid first attribute name, this has to be %v but is %v", "position", firstEntry.AttributeName)
   362  	}
   363  	firstKey, err := GetKForAttribute("position", preK0, tcert)
   364  	if err != nil {
   365  		t.Error(err)
   366  	}
   367  
   368  	if bytes.Compare(firstKey, firstEntry.AttributeKey) != 0 {
   369  		t.Errorf("Invalid K for first attribute expected %v but returned %v", firstKey, firstEntry.AttributeKey)
   370  	}
   371  }
   372  
   373  func TestCreateAttributesMetadata(t *testing.T) {
   374  	tcert, preK0, err := loadTCertAndPreK0()
   375  
   376  	if err != nil {
   377  		t.Error(err)
   378  	}
   379  	tcertRaw := tcert.Raw
   380  	metadata := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
   381  	attributeKeys := []string{"position"}
   382  	metadataObjRaw, err := CreateAttributesMetadata(tcertRaw, metadata, preK0, attributeKeys)
   383  	if err != nil {
   384  		t.Error(err)
   385  	}
   386  
   387  	var metadataObj pb.AttributesMetadata
   388  	err = proto.Unmarshal(metadataObjRaw, &metadataObj)
   389  	if err != nil {
   390  		t.Error(err)
   391  	}
   392  
   393  	if bytes.Compare(metadataObj.Metadata, metadata) != 0 {
   394  		t.Errorf("Invalid metadata result %v but expected %v", metadataObj.Metadata, metadata)
   395  	}
   396  
   397  	entries := metadataObj.GetEntries()
   398  	if len(entries) != 2 {
   399  		t.Errorf("Invalid entries in metadata result %v but expected %v", len(entries), 3)
   400  	}
   401  
   402  	firstEntry := entries[0]
   403  	if firstEntry.AttributeName != "position" {
   404  		t.Errorf("Invalid first attribute name, this has to be %v but is %v", "position", firstEntry.AttributeName)
   405  	}
   406  	firstKey, err := GetKForAttribute("position", preK0, tcert)
   407  	if err != nil {
   408  		t.Error(err)
   409  	}
   410  
   411  	if bytes.Compare(firstKey, firstEntry.AttributeKey) != 0 {
   412  		t.Errorf("Invalid K for first attribute expected %v but returned %v", firstKey, firstEntry.AttributeKey)
   413  	}
   414  }
   415  
   416  func TestCreateAttributesMetadata_AttributeNotFound(t *testing.T) {
   417  	tcert, preK0, err := loadTCertAndPreK0()
   418  
   419  	if err != nil {
   420  		t.Error(err)
   421  	}
   422  	tcertRaw := tcert.Raw
   423  	metadata := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
   424  	attributeKeys := []string{"company"}
   425  	metadataObjRaw, err := CreateAttributesMetadata(tcertRaw, metadata, preK0, attributeKeys)
   426  	if err != nil {
   427  		t.Error(err)
   428  	}
   429  
   430  	var metadataObj pb.AttributesMetadata
   431  	err = proto.Unmarshal(metadataObjRaw, &metadataObj)
   432  	if err != nil {
   433  		t.Error(err)
   434  	}
   435  	if bytes.Compare(metadataObj.Metadata, metadata) != 0 {
   436  		t.Errorf("Invalid metadata result %v but expected %v", metadataObj.Metadata, metadata)
   437  	}
   438  
   439  	entries := metadataObj.GetEntries()
   440  	if len(entries) != 2 {
   441  		t.Errorf("Invalid entries in metadata result %v but expected %v", len(entries), 3)
   442  	}
   443  
   444  	firstEntry := entries[0]
   445  	if firstEntry.AttributeName != "company" {
   446  		t.Errorf("Invalid first attribute name, this has to be %v but is %v", "position", firstEntry.AttributeName)
   447  	}
   448  	_, err = GetKForAttribute("company", preK0, tcert)
   449  	if err == nil {
   450  		t.Fatalf("Test should faild because company is not included within the TCert.")
   451  	}
   452  }
   453  
   454  func TestCreateAttributesMetadataObjectFromCert_AttributeNotFound(t *testing.T) {
   455  	tcert, preK0, err := loadTCertAndPreK0()
   456  	if err != nil {
   457  		t.Error(err)
   458  	}
   459  
   460  	metadata := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
   461  	attributeKeys := []string{"company"}
   462  	metadataObj := CreateAttributesMetadataObjectFromCert(tcert, metadata, preK0, attributeKeys)
   463  	if bytes.Compare(metadataObj.Metadata, metadata) != 0 {
   464  		t.Errorf("Invalid metadata result %v but expected %v", metadataObj.Metadata, metadata)
   465  	}
   466  
   467  	entries := metadataObj.GetEntries()
   468  	if len(entries) != 2 {
   469  		t.Errorf("Invalid entries in metadata result %v but expected %v", len(entries), 3)
   470  	}
   471  
   472  	firstEntry := entries[0]
   473  	if firstEntry.AttributeName != "company" {
   474  		t.Errorf("Invalid first attribute name, this has to be %v but is %v", "position", firstEntry.AttributeName)
   475  	}
   476  	_, err = GetKForAttribute("company", preK0, tcert)
   477  	if err == nil {
   478  		t.Fatalf("Test should faild because company is not included within the TCert.")
   479  	}
   480  }
   481  
   482  func TestBuildAttributesHeader(t *testing.T) {
   483  	attributes := make(map[string]int)
   484  	attributes["company"] = 0
   485  	attributes["position"] = 1
   486  	attributes["country"] = 2
   487  	result, err := BuildAttributesHeader(attributes)
   488  	if err != nil {
   489  		t.Error(err)
   490  	}
   491  
   492  	resultStr := string(result)
   493  
   494  	if !strings.HasPrefix(resultStr, headerPrefix) {
   495  		t.Fatalf("Invalid header prefix expected %v result %v", headerPrefix, resultStr)
   496  	}
   497  
   498  	if !strings.Contains(resultStr, "company->0#") {
   499  		t.Fatalf("Invalid header shoud include '%v'", "company->0#")
   500  	}
   501  
   502  	if !strings.Contains(resultStr, "position->1#") {
   503  		t.Fatalf("Invalid header shoud include '%v'", "position->1#")
   504  	}
   505  
   506  	if !strings.Contains(resultStr, "country->2#") {
   507  		t.Fatalf("Invalid header shoud include '%v'", "country->2#")
   508  	}
   509  }
   510  
   511  func TestBuildAttributesHeader_DuplicatedPosition(t *testing.T) {
   512  	attributes := make(map[string]int)
   513  	attributes["company"] = 0
   514  	attributes["position"] = 0
   515  	attributes["country"] = 1
   516  	_, err := BuildAttributesHeader(attributes)
   517  	if err == nil {
   518  		t.Fatalf("Error this tests should fail because header has two attributes with the same position")
   519  	}
   520  }
   521  
   522  func loadTCertAndPreK0() (*x509.Certificate, []byte, error) {
   523  	preKey0, err := ioutil.ReadFile("./test_resources/prek0.dump")
   524  	if err != nil {
   525  		return nil, nil, err
   526  	}
   527  
   528  	if err != nil {
   529  		return nil, nil, err
   530  	}
   531  
   532  	tcertRaw, err := ioutil.ReadFile("./test_resources/tcert.dump")
   533  	if err != nil {
   534  		return nil, nil, err
   535  	}
   536  
   537  	tcertDecoded, _ := pem.Decode(tcertRaw)
   538  
   539  	tcert, err := x509.ParseCertificate(tcertDecoded.Bytes)
   540  	if err != nil {
   541  		return nil, nil, err
   542  	}
   543  
   544  	return tcert, preKey0, nil
   545  }