@@ -603,6 +603,7 @@ func toHex(s string) string { return hex.EncodeToString([]byte(s)) }
603
603
604
604
func TestGetNodeJoinScript (t * testing.T ) {
605
605
validToken := "f18da1c9f6630a51e8daf121e7451daa"
606
+ validTokenWithLabelsWithSpecialChars := "f18da1c9f6630a51e8daf121e7451dbb"
606
607
validIAMToken := "valid-iam-token"
607
608
internalResourceID := "967d38ff-7a61-4f42-bd2d-c61965b44db0"
608
609
@@ -618,27 +619,33 @@ func TestGetNodeJoinScript(t *testing.T) {
618
619
return & proto.GetClusterCACertResponse {TLSCA : fakeBytes }, nil
619
620
},
620
621
mockGetToken : func (_ context.Context , token string ) (types.ProvisionToken , error ) {
621
- if token == validToken || token == validIAMToken {
622
- return & types.ProvisionTokenV2 {
623
- Metadata : types.Metadata {
624
- Name : token ,
625
- },
626
- Spec : types.ProvisionTokenSpecV2 {
627
- SuggestedLabels : types.Labels {
628
- types .InternalResourceIDLabel : utils.Strings {internalResourceID },
629
- },
622
+ baseToken := & types.ProvisionTokenV2 {
623
+ Metadata : types.Metadata {
624
+ Name : token ,
625
+ },
626
+ Spec : types.ProvisionTokenSpecV2 {
627
+ SuggestedLabels : types.Labels {
628
+ types .InternalResourceIDLabel : utils.Strings {internalResourceID },
630
629
},
631
- }, nil
630
+ },
632
631
}
633
- return nil , trace .NotFound ("token does not exist" )
632
+ switch token {
633
+ case validToken , validIAMToken :
634
+ case validTokenWithLabelsWithSpecialChars :
635
+ baseToken .Spec .SuggestedLabels ["env" ] = []string {"bad label value | ; & $ > < ' !" }
636
+ baseToken .Spec .SuggestedLabels ["bad label key | ; & $ > < ' !" ] = []string {"env" }
637
+ default :
638
+ return nil , trace .NotFound ("token does not exist" )
639
+ }
640
+ return baseToken , nil
634
641
},
635
642
}
636
643
637
644
for _ , test := range []struct {
638
645
desc string
639
646
settings scriptSettings
640
647
errAssert require.ErrorAssertionFunc
641
- extraAssertions func (script string )
648
+ extraAssertions func (t * testing. T , script string )
642
649
}{
643
650
{
644
651
desc : "zero value" ,
@@ -659,7 +666,7 @@ func TestGetNodeJoinScript(t *testing.T) {
659
666
desc : "valid" ,
660
667
settings : scriptSettings {token : validToken },
661
668
errAssert : require .NoError ,
662
- extraAssertions : func (script string ) {
669
+ extraAssertions : func (t * testing. T , script string ) {
663
670
require .Contains (t , script , validToken )
664
671
require .Contains (t , script , "test-host" )
665
672
require .Contains (t , script , "12345678" )
@@ -682,19 +689,28 @@ func TestGetNodeJoinScript(t *testing.T) {
682
689
joinMethod : string (types .JoinMethodIAM ),
683
690
},
684
691
errAssert : require .NoError ,
685
- extraAssertions : func (script string ) {
692
+ extraAssertions : func (t * testing. T , script string ) {
686
693
require .Contains (t , script , "JOIN_METHOD='iam'" )
687
694
},
688
695
},
689
696
{
690
697
desc : "internal resourceid label" ,
691
698
settings : scriptSettings {token : validToken },
692
699
errAssert : require .NoError ,
693
- extraAssertions : func (script string ) {
700
+ extraAssertions : func (t * testing. T , script string ) {
694
701
require .Contains (t , script , "--labels " )
695
702
require .Contains (t , script , fmt .Sprintf ("%s=%s" , types .InternalResourceIDLabel , internalResourceID ))
696
703
},
697
704
},
705
+ {
706
+ desc : "attempt to shell injection using suggested labels" ,
707
+ settings : scriptSettings {token : validTokenWithLabelsWithSpecialChars },
708
+ errAssert : require .NoError ,
709
+ extraAssertions : func (t * testing.T , script string ) {
710
+ require .Contains (t , script , `bad\ label\ key\ \|\ \;\ \&\ \$\ \>\ \<\ \'\ \!=env` )
711
+ require .Contains (t , script , `env=bad\ label\ value\ \|\ \;\ \&\ \$\ \>\ \<\ \'\ \!` )
712
+ },
713
+ },
698
714
} {
699
715
t .Run (test .desc , func (t * testing.T ) {
700
716
script , err := getJoinScript (context .Background (), test .settings , m )
@@ -704,7 +720,7 @@ func TestGetNodeJoinScript(t *testing.T) {
704
720
}
705
721
706
722
if test .extraAssertions != nil {
707
- test .extraAssertions (script )
723
+ test .extraAssertions (t , script )
708
724
}
709
725
})
710
726
}
@@ -899,6 +915,8 @@ func TestGetAppJoinScript(t *testing.T) {
899
915
func TestGetDatabaseJoinScript (t * testing.T ) {
900
916
validToken := "f18da1c9f6630a51e8daf121e7451daa"
901
917
emptySuggestedAgentMatcherLabelsToken := "f18da1c9f6630a51e8daf121e7451000"
918
+ wildcardLabelMatcherToken := "f18da1c9f6630a51e8daf121e7451001"
919
+ tokenWithSpecialChars := "f18da1c9f6630a51e8daf121e7451002"
902
920
internalResourceID := "967d38ff-7a61-4f42-bd2d-c61965b44db0"
903
921
904
922
m := & mockedNodeAPIGetter {
@@ -935,6 +953,22 @@ func TestGetDatabaseJoinScript(t *testing.T) {
935
953
provisionToken .Spec .SuggestedAgentMatcherLabels = types.Labels {}
936
954
return provisionToken , nil
937
955
}
956
+ if token == wildcardLabelMatcherToken {
957
+ provisionToken .Spec .SuggestedAgentMatcherLabels = types.Labels {"*" : []string {"*" }}
958
+ return provisionToken , nil
959
+ }
960
+ if token == tokenWithSpecialChars {
961
+ provisionToken .Spec .SuggestedAgentMatcherLabels = types.Labels {
962
+ "*" : utils.Strings {"*" },
963
+ "spa ces" : utils.Strings {"spa ces" },
964
+ "EOF" : utils.Strings {"test heredoc" },
965
+ `"EOF"` : utils.Strings {"test quoted heredoc" },
966
+ "#'; <>\\ #" : utils.Strings {"try to escape yaml" },
967
+ "&<>'\" $A,./;'BCD ${ABCD}" : utils.Strings {"key with special characters" },
968
+ "value with special characters" : utils.Strings {"&<>'\" $A,./;'BCD ${ABCD}" , "#&<>'\" $A,./;'BCD ${ABCD}" },
969
+ }
970
+ return provisionToken , nil
971
+ }
938
972
return nil , trace .NotFound ("token does not exist" )
939
973
},
940
974
}
@@ -943,7 +977,7 @@ func TestGetDatabaseJoinScript(t *testing.T) {
943
977
desc string
944
978
settings scriptSettings
945
979
errAssert require.ErrorAssertionFunc
946
- extraAssertions func (script string )
980
+ extraAssertions func (t * testing. T , script string )
947
981
}{
948
982
{
949
983
desc : "two installation methods" ,
@@ -961,22 +995,65 @@ func TestGetDatabaseJoinScript(t *testing.T) {
961
995
token : validToken ,
962
996
},
963
997
errAssert : require .NoError ,
964
- extraAssertions : func (script string ) {
998
+ extraAssertions : func (t * testing. T , script string ) {
965
999
require .Contains (t , script , validToken )
966
1000
require .Contains (t , script , "test-host" )
967
1001
require .Contains (t , script , "sha256:" )
968
1002
require .Contains (t , script , "--labels " )
969
1003
require .Contains (t , script , fmt .Sprintf ("%s=%s" , types .InternalResourceIDLabel , internalResourceID ))
970
1004
require .Contains (t , script , `
971
- db_service:
972
- enabled: "yes"
973
- resources:
974
1005
- labels:
975
1006
env: prod
976
1007
os:
977
1008
- mac
978
1009
- linux
979
1010
product: '*'
1011
+ ` )
1012
+ },
1013
+ },
1014
+ {
1015
+ desc : "discover flow with wildcard label matcher" ,
1016
+ settings : scriptSettings {
1017
+ databaseInstallMode : true ,
1018
+ token : wildcardLabelMatcherToken ,
1019
+ },
1020
+ errAssert : require .NoError ,
1021
+ extraAssertions : func (t * testing.T , script string ) {
1022
+ require .Contains (t , script , wildcardLabelMatcherToken )
1023
+ require .Contains (t , script , "test-host" )
1024
+ require .Contains (t , script , "sha256:" )
1025
+ require .Contains (t , script , "--labels " )
1026
+ require .Contains (t , script , fmt .Sprintf ("%s=%s" , types .InternalResourceIDLabel , internalResourceID ))
1027
+ require .Contains (t , script , `
1028
+ - labels:
1029
+ '*': '*'
1030
+ ` )
1031
+ },
1032
+ },
1033
+ {
1034
+ desc : "discover flow with shell injection attempt in resource matcher labels" ,
1035
+ settings : scriptSettings {
1036
+ databaseInstallMode : true ,
1037
+ token : tokenWithSpecialChars ,
1038
+ },
1039
+ errAssert : require .NoError ,
1040
+ extraAssertions : func (t * testing.T , script string ) {
1041
+ require .Contains (t , script , tokenWithSpecialChars )
1042
+ require .Contains (t , script , "test-host" )
1043
+ require .Contains (t , script , "sha256:" )
1044
+ require .Contains (t , script , "--labels " )
1045
+ require .Contains (t , script , fmt .Sprintf ("%s=%s" , types .InternalResourceIDLabel , internalResourceID ))
1046
+ require .Contains (t , script , `
1047
+ - labels:
1048
+ '"EOF"': test quoted heredoc
1049
+ '#''; <>\#': try to escape yaml
1050
+ '&<>''"$A,./;''BCD ${ABCD}': key with special characters
1051
+ '*': '*'
1052
+ EOF: test heredoc
1053
+ spa ces: spa ces
1054
+ value with special characters:
1055
+ - '&<>''"$A,./;''BCD ${ABCD}'
1056
+ - '#&<>''"$A,./;''BCD ${ABCD}'
980
1057
` )
981
1058
},
982
1059
},
@@ -987,16 +1064,13 @@ db_service:
987
1064
token : emptySuggestedAgentMatcherLabelsToken ,
988
1065
},
989
1066
errAssert : require .NoError ,
990
- extraAssertions : func (script string ) {
1067
+ extraAssertions : func (t * testing. T , script string ) {
991
1068
require .Contains (t , script , emptySuggestedAgentMatcherLabelsToken )
992
1069
require .Contains (t , script , "test-host" )
993
1070
require .Contains (t , script , "sha256:" )
994
1071
require .Contains (t , script , "--labels " )
995
1072
require .Contains (t , script , fmt .Sprintf ("%s=%s" , types .InternalResourceIDLabel , internalResourceID ))
996
1073
require .Contains (t , script , `
997
- db_service:
998
- enabled: "yes"
999
- resources:
1000
1074
- labels:
1001
1075
{}
1002
1076
` )
@@ -1011,7 +1085,7 @@ db_service:
1011
1085
}
1012
1086
1013
1087
if test .extraAssertions != nil {
1014
- test .extraAssertions (script )
1088
+ test .extraAssertions (t , script )
1015
1089
}
1016
1090
})
1017
1091
}
0 commit comments