55import com .ayedata .simault .repository .AppRegistryRepository ;
66import com .mongodb .client .MongoClient ;
77import com .mongodb .client .MongoCollection ;
8+ import org .apache .logging .log4j .LogManager ;
9+ import org .apache .logging .log4j .Logger ;
810import org .bson .Document ;
911import org .bson .types .Binary ;
1012import org .springframework .beans .factory .annotation .Value ;
2123@ RequestMapping ("/api/admin" )
2224public class AdminController {
2325
26+ // 1. Initialize Log4j 2 Logger
27+ private static final Logger logger = LogManager .getLogger (AdminController .class );
28+
2429 private final AppRegistryRepository registry ;
2530 private final MongoClient mongoClient ;
2631
@@ -35,8 +40,18 @@ public AdminController(AppRegistryRepository registry, MongoClient mongoClient)
3540 this .mongoClient = mongoClient ;
3641 }
3742
43+ /**
44+ * Helper to check authorization and log failures.
45+ */
3846 private boolean isUnauthorized (String requestKey ) {
39- return requestKey == null || !requestKey .equals (adminApiKey );
47+ // Log the key with "token=" prefix so the Regex Replacement picks it up and redacts it.
48+ logger .debug ("Validating admin access for token={}" , requestKey );
49+
50+ if (requestKey == null || !requestKey .equals (adminApiKey )) {
51+ logger .warn ("Unauthorized access attempt. Invalid or missing API key." );
52+ return true ;
53+ }
54+ return false ;
4055 }
4156
4257 // --- KEY ENDPOINT ---
@@ -52,38 +67,51 @@ public ResponseEntity<VaultKey> findKey(
5267
5368 // 1. Determine which key name to search for
5469 String searchName = (altName != null && !altName .isBlank ()) ? altName : defaultKeyAltName ;
55-
56- // 2. Query MongoDB
57- MongoCollection <Document > keyVault = mongoClient .getDatabase ("encryption" ).getCollection ("__keyVault" );
58- Document keyDoc = keyVault .find (new Document ("keyAltNames" , searchName )).first ();
59-
60- if (keyDoc == null ) {
61- return ResponseEntity .notFound ().build ();
70+ logger .info ("Admin requesting key details for alias: '{}'" , searchName );
71+
72+ try {
73+ // 2. Query MongoDB
74+ MongoCollection <Document > keyVault = mongoClient .getDatabase ("encryption" ).getCollection ("__keyVault" );
75+ Document keyDoc = keyVault .find (new Document ("keyAltNames" , searchName )).first ();
76+
77+ if (keyDoc == null ) {
78+ logger .warn ("Key not found for alias: '{}'" , searchName );
79+ return ResponseEntity .notFound ().build ();
80+ }
81+
82+ // 3. Map BSON to Java Model (VaultKey)
83+ Binary bsonBinary = keyDoc .get ("_id" , Binary .class );
84+ ByteBuffer buffer = ByteBuffer .wrap (bsonBinary .getData ());
85+ UUID keyId = new UUID (buffer .getLong (), buffer .getLong ());
86+
87+ String provider = keyDoc .get ("masterKey" , Document .class ).getString ("provider" );
88+
89+ VaultKey response = new VaultKey (
90+ searchName ,
91+ keyId .toString (),
92+ "Active" ,
93+ provider
94+ );
95+
96+ logger .info ("Key details retrieved successfully for alias: '{}'" , searchName );
97+ return ResponseEntity .ok (response );
98+
99+ } catch (Exception e ) {
100+ logger .error ("Database error while retrieving key for alias: '{}'" , searchName , e );
101+ return ResponseEntity .status (HttpStatus .INTERNAL_SERVER_ERROR ).build ();
62102 }
63-
64- // 3. Map BSON to Java Model (VaultKey)
65- Binary bsonBinary = keyDoc .get ("_id" , Binary .class );
66- ByteBuffer buffer = ByteBuffer .wrap (bsonBinary .getData ());
67- UUID keyId = new UUID (buffer .getLong (), buffer .getLong ());
68-
69- String provider = keyDoc .get ("masterKey" , Document .class ).getString ("provider" );
70-
71- VaultKey response = new VaultKey (
72- searchName ,
73- keyId .toString (),
74- "Active" ,
75- provider
76- );
77-
78- return ResponseEntity .ok (response );
79103 }
80104
81105 // --- APP ENDPOINTS ---
82106
83107 @ GetMapping ("/apps" )
84108 public ResponseEntity <List <AllowedApp >> listApps (@ RequestHeader (value = "X-ADMIN-KEY" , required = false ) String apiKey ) {
85109 if (isUnauthorized (apiKey )) return ResponseEntity .status (HttpStatus .UNAUTHORIZED ).build ();
110+
111+ logger .info ("Fetching list of all allowed apps." );
86112 List <AllowedApp > apps = registry .findAll ();
113+ logger .debug ("Found {} registered apps." , apps .size ());
114+
87115 return ResponseEntity .ok (apps );
88116 }
89117
@@ -95,10 +123,24 @@ public ResponseEntity<String> registerApp(
95123 if (isUnauthorized (apiKey )) return ResponseEntity .status (HttpStatus .UNAUTHORIZED ).body ("⛔ Unauthorized" );
96124
97125 String appId = payload .get ("appId" );
98- if (appId == null || appId .isBlank ()) return ResponseEntity .badRequest ().body ("appId is required" );
126+
127+ // Log the payload safely. If payload contained "key":"..." or "token=...",
128+ // Log4j would automatically redact those specific fields.
129+ logger .info ("Attempting to register app. Payload: {}" , payload );
130+
131+ if (appId == null || appId .isBlank ()) {
132+ logger .warn ("Registration failed: Missing appId in payload." );
133+ return ResponseEntity .badRequest ().body ("appId is required" );
134+ }
99135
100- registry .registerApp (appId , payload .get ("description" ));
101- return ResponseEntity .ok ("✅ App registered: " + appId );
136+ try {
137+ registry .registerApp (appId , payload .get ("description" ));
138+ logger .info ("✅ App registered successfully: {}" , appId );
139+ return ResponseEntity .ok ("✅ App registered: " + appId );
140+ } catch (Exception e ) {
141+ logger .error ("Failed to register app: {}" , appId , e );
142+ return ResponseEntity .status (HttpStatus .INTERNAL_SERVER_ERROR ).body ("Registration failed" );
143+ }
102144 }
103145
104146 @ DeleteMapping ("/apps/{appId}" )
@@ -107,7 +149,16 @@ public ResponseEntity<String> removeApp(
107149 @ PathVariable String appId ) {
108150
109151 if (isUnauthorized (apiKey )) return ResponseEntity .status (HttpStatus .UNAUTHORIZED ).body ("⛔ Unauthorized" );
110- registry .removeApp (appId );
111- return ResponseEntity .ok ("🚫 Access revoked for: " + appId );
152+
153+ logger .info ("Attempting to revoke access for app: {}" , appId );
154+
155+ try {
156+ registry .removeApp (appId );
157+ logger .info ("🚫 Access revoked successfully for: {}" , appId );
158+ return ResponseEntity .ok ("🚫 Access revoked for: " + appId );
159+ } catch (Exception e ) {
160+ logger .error ("Failed to revoke app: {}" , appId , e );
161+ return ResponseEntity .status (HttpStatus .INTERNAL_SERVER_ERROR ).body ("Revocation failed" );
162+ }
112163 }
113164}
0 commit comments