21
21
using Confluent . Kafka . Admin ;
22
22
using System . Linq ;
23
23
using System . Collections . Generic ;
24
+ using System . Text ;
24
25
25
26
26
27
namespace Confluent . Kafka . Examples
@@ -161,6 +162,85 @@ static void PrintAclBindings(List<AclBinding> aclBindings)
161
162
}
162
163
}
163
164
165
+ static List < UserScramCredentialAlteration > ParseUserScramCredentialAlterations (
166
+ string [ ] args )
167
+ {
168
+ if ( args . Length == 0 )
169
+ {
170
+ Console . WriteLine ( "usage: .. <bootstrapServers> alter-user-scram-alterations " +
171
+ "UPSERT <user1> <mechanism1> <iterations1> <password1> <salt1> " +
172
+ "[UPSERT <user2> <mechanism2> <iterations2> <password2> <salt2> " +
173
+ "DELETE <user3> <mechanism3> ..]" ) ;
174
+ Environment . ExitCode = 1 ;
175
+ return null ;
176
+ }
177
+
178
+ var alterations = new List < UserScramCredentialAlteration > ( ) ;
179
+ for ( int i = 0 ; i < args . Length ; ) {
180
+ string alterationName = args [ i ] ;
181
+ if ( alterationName == "UPSERT" )
182
+ {
183
+ if ( i + 5 >= args . Length )
184
+ {
185
+ throw new ArgumentException (
186
+ $ "invalid number of arguments for alteration { alterations . Count } ,"+
187
+ $ " expected 5, got { args . Length - i - 1 } ") ;
188
+ }
189
+
190
+ string user = args [ i + 1 ] ;
191
+ var mechanism = Enum . Parse < ScramMechanism > ( args [ i + 2 ] ) ;
192
+ var iterations = Int32 . Parse ( args [ i + 3 ] ) ;
193
+ var password = Encoding . UTF8 . GetBytes ( args [ i + 4 ] ) ;
194
+ string saltString = args [ i + 5 ] ;
195
+ byte [ ] salt = null ;
196
+ if ( saltString != "" )
197
+ {
198
+ salt = Encoding . UTF8 . GetBytes ( saltString ) ;
199
+ }
200
+ alterations . Add (
201
+ new UserScramCredentialUpsertion
202
+ {
203
+ User = user ,
204
+ ScramCredentialInfo = new ScramCredentialInfo
205
+ {
206
+ Mechanism = mechanism ,
207
+ Iterations = iterations ,
208
+ } ,
209
+ Password = password ,
210
+ Salt = salt ,
211
+ }
212
+ ) ;
213
+ i += 6 ;
214
+ }
215
+ else if ( alterationName == "DELETE" )
216
+ {
217
+ if ( i + 2 >= args . Length )
218
+ {
219
+ throw new ArgumentException (
220
+ $ "invalid number of arguments for alteration { alterations . Count } ,"+
221
+ $ " expected 2, got { args . Length - i - 1 } ") ;
222
+ }
223
+
224
+ string user = args [ i + 1 ] ;
225
+ var mechanism = Enum . Parse < ScramMechanism > ( args [ i + 2 ] ) ;
226
+ alterations . Add (
227
+ new UserScramCredentialDeletion
228
+ {
229
+ User = user ,
230
+ Mechanism = mechanism ,
231
+ }
232
+ ) ;
233
+ i += 3 ;
234
+ }
235
+ else
236
+ {
237
+ throw new ArgumentException (
238
+ $ "invalid alteration { alterations . Count } , must be UPSERT or DELETE") ;
239
+ }
240
+ }
241
+ return alterations ;
242
+ }
243
+
164
244
static async Task CreateAclsAsync ( string bootstrapServers , string [ ] commandArgs )
165
245
{
166
246
List < AclBinding > aclBindings ;
@@ -599,6 +679,84 @@ e is FormatException
599
679
}
600
680
}
601
681
682
+ static async Task DescribeUserScramCredentialsAsync ( string bootstrapServers , string [ ] commandArgs )
683
+ {
684
+ var users = commandArgs . ToList ( ) ;
685
+ var timeout = TimeSpan . FromSeconds ( 30 ) ;
686
+ using ( var adminClient = new AdminClientBuilder ( new AdminClientConfig { BootstrapServers = bootstrapServers } ) . Build ( ) )
687
+ {
688
+ try
689
+ {
690
+ var descResult = await adminClient . DescribeUserScramCredentialsAsync ( users , new DescribeUserScramCredentialsOptions ( ) { RequestTimeout = timeout } ) ;
691
+ foreach ( var description in descResult . UserScramCredentialsDescriptions )
692
+ {
693
+ Console . WriteLine ( $ " User: { description . User } ") ;
694
+ foreach ( var scramCredentialInfo in description . ScramCredentialInfos )
695
+ {
696
+ Console . WriteLine ( $ " Mechanism: { scramCredentialInfo . Mechanism } ") ;
697
+ Console . WriteLine ( $ " Iterations: { scramCredentialInfo . Iterations } ") ;
698
+ }
699
+ }
700
+ }
701
+ catch ( DescribeUserScramCredentialsException e )
702
+ {
703
+ Console . WriteLine ( $ "An error occurred describing user SCRAM credentials" +
704
+ " for some users:" ) ;
705
+ foreach ( var description in e . Results . UserScramCredentialsDescriptions )
706
+ {
707
+ Console . WriteLine ( $ " User: { description . User } ") ;
708
+ Console . WriteLine ( $ " Error: { description . Error } ") ;
709
+ if ( ! description . Error . IsError )
710
+ {
711
+ foreach ( var scramCredentialInfo in description . ScramCredentialInfos )
712
+ {
713
+ Console . WriteLine ( $ " Mechanism: { scramCredentialInfo . Mechanism } ") ;
714
+ Console . WriteLine ( $ " Iterations: { scramCredentialInfo . Iterations } ") ;
715
+ }
716
+ }
717
+ }
718
+ }
719
+ catch ( KafkaException e )
720
+ {
721
+ Console . WriteLine ( $ "An error occurred describing user SCRAM credentials: { e } ") ;
722
+ Environment . ExitCode = 1 ;
723
+ }
724
+ }
725
+ }
726
+
727
+ static async Task AlterUserScramCredentialsAsync ( string bootstrapServers , string [ ] commandArgs )
728
+ {
729
+ var alterations = ParseUserScramCredentialAlterations ( commandArgs ) ;
730
+ if ( alterations == null )
731
+ return ;
732
+
733
+ var timeout = TimeSpan . FromSeconds ( 30 ) ;
734
+ using ( var adminClient = new AdminClientBuilder ( new AdminClientConfig { BootstrapServers = bootstrapServers } ) . Build ( ) )
735
+ {
736
+ try
737
+ {
738
+ await adminClient . AlterUserScramCredentialsAsync ( alterations ,
739
+ new AlterUserScramCredentialsOptions ( ) { RequestTimeout = timeout } ) ;
740
+ Console . WriteLine ( "All AlterUserScramCredentials operations completed successfully" ) ;
741
+ }
742
+ catch ( AlterUserScramCredentialsException e )
743
+ {
744
+ Console . WriteLine ( $ "An error occurred altering user SCRAM credentials" +
745
+ " for some users:" ) ;
746
+ foreach ( var result in e . Results )
747
+ {
748
+ Console . WriteLine ( $ " User: { result . User } ") ;
749
+ Console . WriteLine ( $ " Error: { result . Error } ") ;
750
+ }
751
+ }
752
+ catch ( KafkaException e )
753
+ {
754
+ Console . WriteLine ( $ "An error occurred altering user SCRAM credentials: { e } ") ;
755
+ Environment . ExitCode = 1 ;
756
+ }
757
+ }
758
+ }
759
+
602
760
public static async Task Main ( string [ ] args )
603
761
{
604
762
if ( args . Length < 2 )
@@ -609,7 +767,9 @@ public static async Task Main(string[] args)
609
767
"describe-acls" , "delete-acls" ,
610
768
"list-consumer-groups" , "describe-consumer-groups" ,
611
769
"list-consumer-group-offsets" , "alter-consumer-group-offsets" ,
612
- "incremental-alter-configs"
770
+ "incremental-alter-configs" , "describe-user-scram-credentials" ,
771
+ "alter-user-scram-credentials"
772
+
613
773
} ) +
614
774
" .." ) ;
615
775
Environment . ExitCode = 1 ;
@@ -658,6 +818,12 @@ public static async Task Main(string[] args)
658
818
case "incremental-alter-configs" :
659
819
await IncrementalAlterConfigsAsync ( bootstrapServers , commandArgs ) ;
660
820
break ;
821
+ case "describe-user-scram-credentials" :
822
+ await DescribeUserScramCredentialsAsync ( bootstrapServers , commandArgs ) ;
823
+ break ;
824
+ case "alter-user-scram-credentials" :
825
+ await AlterUserScramCredentialsAsync ( bootstrapServers , commandArgs ) ;
826
+ break ;
661
827
default :
662
828
Console . WriteLine ( $ "unknown command: { command } ") ;
663
829
break ;
0 commit comments