@@ -2,6 +2,7 @@ package firewall
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"fmt"
6
7
"testing"
7
8
"time"
@@ -718,6 +719,196 @@ func TestHideBool(t *testing.T) {
718
719
require .False (t , val )
719
720
}
720
721
722
+ // TestObfuscateConfig tests that we substitute substrings in the config
723
+ // correctly.
724
+ func TestObfuscateConfig (t * testing.T ) {
725
+ tests := []struct {
726
+ name string
727
+ config []byte
728
+ knownMap map [string ]string
729
+ expectedNewPairs int
730
+ expectErr bool
731
+ notExpectSameLen bool
732
+ }{
733
+ {
734
+ name : "empty" ,
735
+ },
736
+ {
737
+ // We substitue pubkeys of different forms.
738
+ name : "several pubkeys" ,
739
+ config : []byte (`{"version":1,"list":` +
740
+ `["d23da57575cdcb878ac191e1e0c8a5c4f061b11cfdc7a8ec5c9d495270de66fdbf",` +
741
+ `"0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca85",` +
742
+ `"DEAD2708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca85",` +
743
+ `"586b59212da4623c40dcc68c4573da1719e5893630790c9f2db8940fff3efd8cd4"]}` ),
744
+ expectedNewPairs : 4 ,
745
+ },
746
+ {
747
+ // We don't generate new pairs for pubkeys that we
748
+ // already have a mapping.
749
+ name : "several pubkeys with known replacement or duplicates" ,
750
+ config : []byte (`{"version":1,"list":` +
751
+ `["d23da57575cdcb878ac191e1e0c8a5c4f061b11cfdc7a8ec5c9d495270de66fdbf",` +
752
+ `"0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca85",` +
753
+ `"DEAD2708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca85",` +
754
+ `"0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca85",` +
755
+ `"586b59212da4623c40dcc68c4573da1719e5893630790c9f2db8940fff3efd8cd4"]}` ),
756
+ knownMap : map [string ]string {
757
+ "586b59212da4623c40dcc68c4573da1719e5893630790c9f2db8940fff3efd8cd4" : "123456789012345678901234567890123456789012345678901234567890123456" ,
758
+ },
759
+ expectedNewPairs : 3 ,
760
+ },
761
+ {
762
+ // We don't substitute unknown items.
763
+ name : "all invalid pubkeys" ,
764
+ config : []byte (`{"version":1,"list":` +
765
+ `["d23da57575cdcb878ac191e1e0c8a5c4f061b11",` +
766
+ `"586b59212da4623c40dcc68c4573da1719e5893630790c9f2db8940fff3efd8cd4dead",` +
767
+ `"x86b59212da4623c40dcc68c4573da1719e5893630790c9f2db8940fff3efd8cd4"]}` ),
768
+ expectedNewPairs : 0 ,
769
+ },
770
+ {
771
+ // We only substitute channel ids that have a sane
772
+ // format.
773
+ name : "channel ids" ,
774
+ config : []byte (`{"version":1,"list":` +
775
+ `["1",` +
776
+ `"12345",` +
777
+ `"1234567890123",` +
778
+ `"1234567890123456789",` +
779
+ `"123456789012345678901"]}` ),
780
+ expectedNewPairs : 2 ,
781
+ },
782
+ {
783
+ // We obfuscate channel points, the character length may
784
+ // vary due to the output index.
785
+ name : "channel points" ,
786
+ config : []byte (`{"version":1,"list":` +
787
+ `["0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca:1",` +
788
+ `"e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca:1",` +
789
+ `"0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca3:1",` +
790
+ `"0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca:3000"]}` ),
791
+ expectedNewPairs : 2 ,
792
+ notExpectSameLen : true ,
793
+ },
794
+ {
795
+ // We only act on items that are in lists of strings.
796
+ name : "single pubkey with another field" ,
797
+ config : []byte (`{"version":1,"list":` +
798
+ `["586b59212da4623c40dcc68c4573da1719e5893630790c9f2db8940fff3efd8cd4"],` +
799
+ `"another":"0e092708c9e737115ff14a85b65466561280d77c1b8cd666bc655536ad81ccca85"}` ),
800
+ expectedNewPairs : 1 ,
801
+ },
802
+ {
803
+ // We don't obfuscate any numbers even though they may
804
+ // be channel ids. This is to be able to set numerical
805
+ // values in the range of channel ids.
806
+ name : "number" ,
807
+ config : []byte (`{"version":1,"number":12345678901234567890}` ),
808
+ expectedNewPairs : 0 ,
809
+ },
810
+ {
811
+ // We don't allow to mix strings with other types, which
812
+ // may be a configuration mistake.
813
+ name : "list of invalid types" ,
814
+ config : []byte (`{"version":1,"channels":` +
815
+ `[12345,` +
816
+ `"e092708c9e737115ff14a85ab65466561280d77c1b8cd666bc655536ad81ccca:1"]}` ),
817
+ expectErr : true ,
818
+ expectedNewPairs : 0 ,
819
+ },
820
+ {
821
+ // A list of numbers is not obfuscated. Those can be
822
+ // useful to submit histograms for example.
823
+ name : "channel ids" ,
824
+ config : []byte (`{"version":1,"list":` +
825
+ `[1,` +
826
+ `12345,` +
827
+ `1234567890123,` +
828
+ `1234567890123456789,` +
829
+ `123456789012345678901]}` ),
830
+ expectedNewPairs : 0 ,
831
+ },
832
+ }
833
+
834
+ // assertConfigStructure checks that the structure of the config is
835
+ // preserved.
836
+ assertConfigStructure := func (wantConfig , gotConfig []byte ) {
837
+ t .Helper ()
838
+
839
+ if len (wantConfig ) == 0 {
840
+ require .Equal (t , wantConfig , gotConfig )
841
+
842
+ return
843
+ }
844
+
845
+ var wantConfigMap map [string ]any
846
+ err := json .Unmarshal (wantConfig , & wantConfigMap )
847
+ require .NoError (t , err )
848
+
849
+ var gotConfigMap map [string ]any
850
+ err = json .Unmarshal (gotConfig , & gotConfigMap )
851
+ require .NoError (t , err )
852
+
853
+ // We test that the number of top level items is the same.
854
+ require .Equal (t , len (wantConfigMap ), len (gotConfigMap ))
855
+
856
+ listLen := func (config map [string ]any ) int {
857
+ for k , v := range config {
858
+ if k == "list" {
859
+ list , ok := v .([]interface {})
860
+ require .True (t , ok )
861
+ return len (list )
862
+ }
863
+ }
864
+ return 0
865
+ }
866
+
867
+ // We test that we have the same number of items in the list.
868
+ require .Equal (t , listLen (wantConfigMap ), listLen (gotConfigMap ))
869
+ }
870
+
871
+ for _ , tt := range tests {
872
+ tt := tt
873
+
874
+ t .Run (tt .name , func (t * testing.T ) {
875
+ t .Parallel ()
876
+
877
+ db := firewalldb .NewPrivacyMapPairs (tt .knownMap )
878
+
879
+ config , privMapPairs , err := ObfuscateConfig (
880
+ db , tt .config ,
881
+ )
882
+ if tt .expectErr {
883
+ require .Error (t , err )
884
+ return
885
+ }
886
+ require .NoError (t , err )
887
+
888
+ // We expect the config to be obfuscated in any parts
889
+ // only if there is sensitive data.
890
+ if tt .expectedNewPairs > 0 {
891
+ require .NotEqual (t , config , tt .config )
892
+ }
893
+
894
+ // We check that we recognized the correct number of new
895
+ // substitutions.
896
+ require .Equal (t , tt .expectedNewPairs ,
897
+ len (privMapPairs ))
898
+
899
+ // We expect the same number of items in the config
900
+ // after obfuscation.
901
+ assertConfigStructure (tt .config , config )
902
+
903
+ // We don't perform exact length checks for cases where
904
+ // we know the length can change.
905
+ if ! tt .notExpectSameLen {
906
+ require .Equal (t , len (tt .config ), len (config ))
907
+ }
908
+ })
909
+ }
910
+ }
911
+
721
912
// mean computes the mean of the given slice of numbers.
722
913
func mean (numbers []uint64 ) uint64 {
723
914
sum := uint64 (0 )
0 commit comments