@@ -23,6 +23,7 @@ import (
2323 "context"
2424 "errors"
2525 "net/http"
26+ "strings"
2627 "testing"
2728 "time"
2829
@@ -309,3 +310,161 @@ func Test_CompactDatabases(t *testing.T) {
309310 })
310311 })
311312}
313+
314+ // Test_GetTLSData checks that TLS configuration data is available and valid, skipping if not configured.
315+ func Test_GetTLSData (t * testing.T ) {
316+ Wrap (t , func (t * testing.T , client arangodb.Client ) {
317+ withContextT (t , time .Minute , func (ctx context.Context , t testing.TB ) {
318+ db , err := client .GetDatabase (ctx , "_system" , nil )
319+ require .NoError (t , err )
320+
321+ // Get TLS data using the client (which embeds ClientAdmin)
322+ tlsResp , err := client .GetTLSData (ctx , db .Name ())
323+ if err != nil {
324+ var arangoErr shared.ArangoError
325+ if errors .As (err , & arangoErr ) {
326+ t .Logf ("GetTLSData failed with ArangoDB error code: %d" , arangoErr .Code )
327+ switch arangoErr .Code {
328+ case 403 :
329+ t .Skip ("Skipping TLS get test - authentication/permission denied (HTTP 403)" )
330+ default :
331+ t .Logf ("Unexpected ArangoDB error code: %d, message: %s" , arangoErr .Code , arangoErr .ErrorMessage )
332+ }
333+ return
334+ }
335+ // Skip for any other error (TLS not configured, network issues, etc.)
336+ t .Logf ("GetTLSData failed: %v" , err )
337+ t .Skip ("Skipping TLS get test - likely TLS not configured or other server issue" )
338+ }
339+
340+ // Success! Validate response structure
341+ t .Logf ("TLS data retrieved successfully" )
342+
343+ // Validate TLS response data
344+ validateTLSResponse (t , tlsResp , "Retrieved" )
345+ })
346+ })
347+ }
348+
349+ // validateTLSResponse is a helper function to validate TLS response data
350+ func validateTLSResponse (t testing.TB , tlsResp arangodb.TLSDataResponse , operation string ) {
351+ // Basic validation - at least one field should be populated
352+ hasData := false
353+ if tlsResp .Keyfile != nil {
354+ if tlsResp .Keyfile .Sha256 != nil && * tlsResp .Keyfile .Sha256 != "" {
355+ t .Logf ("%s keyfile SHA256: %s" , operation , * tlsResp .Keyfile .Sha256 )
356+ hasData = true
357+ }
358+ if len (tlsResp .Keyfile .Certificates ) > 0 {
359+ t .Logf ("%s keyfile contains %d certificates" , operation , len (tlsResp .Keyfile .Certificates ))
360+ hasData = true
361+
362+ // Validate certificate content (basic PEM format check)
363+ for i , cert := range tlsResp .Keyfile .Certificates {
364+ require .NotEmpty (t , cert , "Certificate %d should not be empty" , i )
365+ // Basic PEM format validation
366+ if ! strings .Contains (cert , "-----BEGIN CERTIFICATE-----" ) {
367+ t .Logf ("Warning: Certificate %d may not be in PEM format" , i )
368+ } else {
369+ t .Logf ("Certificate %d appears to be valid PEM format" , i )
370+ }
371+ }
372+ }
373+ if tlsResp .Keyfile .PrivateKeySha256 != nil && * tlsResp .Keyfile .PrivateKeySha256 != "" {
374+ t .Logf ("%s keyfile private key SHA256: %s" , operation , * tlsResp .Keyfile .PrivateKeySha256 )
375+ hasData = true
376+ }
377+ }
378+ if tlsResp .ClientCA != nil && tlsResp .ClientCA .Sha256 != nil && * tlsResp .ClientCA .Sha256 != "" {
379+ t .Logf ("%s client CA SHA256: %s" , operation , * tlsResp .ClientCA .Sha256 )
380+ hasData = true
381+ }
382+ if len (tlsResp .SNI ) > 0 {
383+ t .Logf ("%s SNI configurations found: %d" , operation , len (tlsResp .SNI ))
384+ hasData = true
385+ }
386+ if hasData {
387+ t .Logf ("TLS configuration data validated successfully" )
388+ } else {
389+ t .Logf ("TLS endpoint accessible but no TLS data returned - server may not have TLS configured" )
390+ }
391+ }
392+
393+ // Test_ReloadTLSData tests TLS certificate reload functionality, skipping if superuser rights unavailable.
394+ func Test_ReloadTLSData (t * testing.T ) {
395+ Wrap (t , func (t * testing.T , client arangodb.Client ) {
396+ withContextT (t , time .Minute , func (ctx context.Context , t testing.TB ) {
397+ // Reload TLS data - requires superuser rights
398+ tlsResp , err := client .ReloadTLSData (ctx )
399+ if err != nil {
400+ var arangoErr shared.ArangoError
401+ if errors .As (err , & arangoErr ) {
402+ t .Logf ("ReloadTLSData failed with ArangoDB error code: %d" , arangoErr .Code )
403+ switch arangoErr .Code {
404+ case 403 :
405+ t .Skip ("Skipping TLS reload test - superuser rights required (HTTP 403)" )
406+ default :
407+ t .Logf ("Unexpected ArangoDB error code: %d, message: %s" , arangoErr .Code , arangoErr .ErrorMessage )
408+ }
409+ return
410+ }
411+ // Skip for any other error (TLS not configured, network issues, etc.)
412+ t .Logf ("ReloadTLSData failed: %v" , err )
413+ t .Skip ("Skipping TLS reload test - likely TLS not configured or other server issue" )
414+ }
415+
416+ // Success! Validate response structure
417+ t .Logf ("TLS data reloaded successfully" )
418+
419+ // Validate TLS response data
420+ validateTLSResponse (t , tlsResp , "Reloaded" )
421+ })
422+ })
423+ }
424+
425+ // Test_RotateEncryptionAtRestKey verifies that the encryption key rotation endpoint works as expected.
426+ // The test is skipped if superuser rights are missing or the feature is disabled/not configured.
427+ func Test_RotateEncryptionAtRestKey (t * testing.T ) {
428+ Wrap (t , func (t * testing.T , client arangodb.Client ) {
429+ withContextT (t , time .Minute , func (ctx context.Context , t testing.TB ) {
430+
431+ // Attempt to rotate encryption at rest key - requires superuser rights
432+ resp , err := client .RotateEncryptionAtRestKey (ctx )
433+ if err != nil {
434+ var arangoErr shared.ArangoError
435+ if errors .As (err , & arangoErr ) {
436+ t .Logf ("RotateEncryptionAtRestKey failed with ArangoDB error code: %d" , arangoErr .Code )
437+ switch arangoErr .Code {
438+ case 403 :
439+ t .Skip ("Skipping RotateEncryptionAtRestKey test - superuser rights required (HTTP 403)" )
440+ case 404 :
441+ t .Skip ("Skipping RotateEncryptionAtRestKey test - encryption key rotation disabled (HTTP 404)" )
442+ default :
443+ t .Logf ("Unexpected ArangoDB error code: %d, message: %s" , arangoErr .Code , arangoErr .ErrorMessage )
444+ t .FailNow ()
445+ }
446+ } else {
447+ t .Fatalf ("RotateEncryptionAtRestKey failed with unexpected error: %v" , err )
448+ }
449+ return
450+ }
451+
452+ // Convert response to JSON for logging
453+ encryptionRespJson , err := utils .ToJSONString (resp )
454+ require .NoError (t , err )
455+ t .Logf ("RotateEncryptionAtRestKey response: %s" , encryptionRespJson )
456+
457+ // Validate the response is not nil
458+ require .NotNil (t , resp , "Expected non-nil response" )
459+ t .Logf ("RotateEncryptionAtRestKey succeeded with %d encryption keys" , len (resp ))
460+
461+ // Validate each encryption key
462+ for i , key := range resp {
463+ // Explicit nil check for pointer
464+ require .NotNil (t , key .SHA256 , "Expected encryption key %d SHA256 not to be nil" , i )
465+ require .NotEmpty (t , * key .SHA256 , "Expected encryption key %d SHA256 not to be empty" , i )
466+ t .Logf ("Encryption key %d SHA256: %s" , i , * key .SHA256 )
467+ }
468+ })
469+ })
470+ }
0 commit comments