2424
2525import java .nio .file .Path ;
2626import java .time .Duration ;
27+ import java .util .LinkedHashMap ;
28+ import java .util .Map ;
2729
2830/**
2931 * Testcontainers wrapper for the Kerby KDC Docker image.
@@ -36,13 +38,16 @@ public class KerbyKdcContainer extends GenericContainer<KerbyKdcContainer> {
3638 public static final String DEFAULT_CLIENT_PRINCIPAL = "client" ;
3739 public static final String DEFAULT_CLIENT_PASSWORD = "client" ;
3840 public static final String DEFAULT_SERVICE_PRINCIPAL = "HTTP/localhost" ;
41+ public static final String DEFAULT_KEYTAB_DIR = "/var/lib/kerby/keytabs" ;
3942 public static final String DEFAULT_SERVICE_KEYTAB = "/var/lib/kerby/keytabs/service.keytab" ;
4043
4144 private String realm = DEFAULT_REALM ;
4245 private String clientPrincipal = DEFAULT_CLIENT_PRINCIPAL ;
4346 private String clientPassword = DEFAULT_CLIENT_PASSWORD ;
4447 private String servicePrincipal = DEFAULT_SERVICE_PRINCIPAL ;
4548 private String serviceKeytab = DEFAULT_SERVICE_KEYTAB ;
49+ private final Map <String , String > extraPrincipals = new LinkedHashMap <>();
50+ private final Map <String , String > extraServicePrincipals = new LinkedHashMap <>();
4651
4752 public KerbyKdcContainer () {
4853 this (DEFAULT_IMAGE_NAME );
@@ -82,6 +87,33 @@ public KerbyKdcContainer withServicePrincipal(String principal, String keytabPat
8287 return applyConfiguration ();
8388 }
8489
90+ public KerbyKdcContainer withPrincipal (String principal , String password ) {
91+ extraPrincipals .put (principal , password );
92+ return applyConfiguration ();
93+ }
94+
95+ public KerbyKdcContainer withPrincipals (Map <String , String > principals ) {
96+ extraPrincipals .putAll (principals );
97+ return applyConfiguration ();
98+ }
99+
100+ public KerbyKdcContainer withServicePrincipals (String ... principals ) {
101+ for (String principal : principals ) {
102+ extraServicePrincipals .put (principal , null );
103+ }
104+ return applyConfiguration ();
105+ }
106+
107+ public KerbyKdcContainer withAdditionalServicePrincipal (String principal ) {
108+ extraServicePrincipals .put (principal , null );
109+ return applyConfiguration ();
110+ }
111+
112+ public KerbyKdcContainer withAdditionalServicePrincipal (String principal , String keytabPath ) {
113+ extraServicePrincipals .put (principal , keytabPath );
114+ return applyConfiguration ();
115+ }
116+
85117 public KerbyKdcContainer withExtraPrincipals (String principals ) {
86118 withEnv ("KERBY_EXTRA_PRINCIPALS" , principals );
87119 return this ;
@@ -112,10 +144,22 @@ public String getServiceKeytab() {
112144 return serviceKeytab ;
113145 }
114146
147+ public String getServiceKeytab (String principal ) {
148+ String keytab = extraServicePrincipals .get (principal );
149+ if (keytab != null ) {
150+ return keytab ;
151+ }
152+ return defaultKeytabPath (principal );
153+ }
154+
115155 public void copyServiceKeytabTo (Path target ) {
116156 copyFileFromContainer (serviceKeytab , target .toAbsolutePath ().toString ());
117157 }
118158
159+ public void copyServiceKeytabTo (String principal , Path target ) {
160+ copyFileFromContainer (getServiceKeytab (principal ), target .toAbsolutePath ().toString ());
161+ }
162+
119163 public String getKdcHost () {
120164 return getHost ();
121165 }
@@ -145,6 +189,8 @@ private KerbyKdcContainer applyConfiguration() {
145189 withEnv ("KERBY_CLIENT_PASSWORD" , clientPassword );
146190 withEnv ("KERBY_SERVICE_PRINCIPAL" , servicePrincipal );
147191 withEnv ("KERBY_SERVICE_KEYTAB" , serviceKeytab );
192+ withEnv ("KERBY_EXTRA_PRINCIPALS" , joinPasswordPrincipals ());
193+ withEnv ("KERBY_EXTRA_SERVICE_PRINCIPALS" , joinServicePrincipals ());
148194 return this ;
149195 }
150196
@@ -154,4 +200,36 @@ private String qualifyPrincipal(String principal) {
154200 }
155201 return principal + "@" + realm ;
156202 }
203+
204+ private String joinPasswordPrincipals () {
205+ StringBuilder value = new StringBuilder ();
206+ for (Map .Entry <String , String > entry : extraPrincipals .entrySet ()) {
207+ appendSeparator (value );
208+ value .append (entry .getKey ()).append (':' ).append (entry .getValue ());
209+ }
210+ return value .toString ();
211+ }
212+
213+ private String joinServicePrincipals () {
214+ StringBuilder value = new StringBuilder ();
215+ for (Map .Entry <String , String > entry : extraServicePrincipals .entrySet ()) {
216+ appendSeparator (value );
217+ value .append (entry .getKey ());
218+ if (entry .getValue () != null ) {
219+ value .append (':' ).append (entry .getValue ());
220+ }
221+ }
222+ return value .toString ();
223+ }
224+
225+ private void appendSeparator (StringBuilder value ) {
226+ if (value .length () > 0 ) {
227+ value .append (',' );
228+ }
229+ }
230+
231+ private String defaultKeytabPath (String principal ) {
232+ return DEFAULT_KEYTAB_DIR + "/" + qualifyPrincipal (principal )
233+ .replace ('/' , '_' ).replace ('@' , '_' ) + ".keytab" ;
234+ }
157235}
0 commit comments