1+ /**
2+ * Licensed to the Apache Software Foundation (ASF) under one
3+ * or more contributor license agreements. See the NOTICE file
4+ * distributed with this work for additional information
5+ * regarding copyright ownership. The ASF licenses this file
6+ * to you under the Apache License, Version 2.0 (the
7+ * "License"); you may not use this file except in compliance
8+ * with the License. You may obtain a copy of the License at
9+ * <p>
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ * <p>
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
18+
19+ package org .apache .hadoop .yarn .server .router ;
20+
21+ import org .apache .hadoop .yarn .api .records .ApplicationId ;
22+ import org .apache .hadoop .yarn .server .federation .store .records .SubClusterId ;
23+ import org .slf4j .Logger ;
24+ import org .slf4j .LoggerFactory ;
25+
26+ /**
27+ * Manages Router audit logs.
28+ * Audit log format is written as key=value pairs. Tab separated.
29+ */
30+ public class RouterAuditLogger {
31+ private static final Logger LOG =
32+ LoggerFactory .getLogger (RouterAuditLogger .class );
33+
34+ private RouterAuditLogger () {
35+ }
36+
37+ enum Keys {USER , OPERATION , TARGET , RESULT , IP , PERMISSIONS , DESCRIPTION , APPID , SUBCLUSTERID }
38+
39+ public static class AuditConstants {
40+ static final String SUCCESS = "SUCCESS" ;
41+ static final String FAILURE = "FAILURE" ;
42+ static final String KEY_VAL_SEPARATOR = "=" ;
43+ static final char PAIR_SEPARATOR = '\t' ;
44+
45+ public static final String GET_NEW_APP = "Get New App" ;
46+ public static final String SUBMIT_NEW_APP = "Submit New App" ;
47+ public static final String FORCE_KILL_APP = "Force Kill App" ;
48+ public static final String GET_APP_REPORT = "Get Application Report" ;
49+ }
50+
51+ /**
52+ * Create a readable and parseable audit log string for a successful event.
53+ *
54+ * @param user User who made the service request to the Router
55+ * @param operation Operation requested by the user.
56+ * @param target The target on which the operation is being performed.
57+ * @param appId Application Id in which operation was performed.
58+ *
59+ * <br><br>
60+ * Note that the {@link RouterAuditLogger} uses tabs ('\t') as a key-val
61+ * delimiter and hence the value fields should not contains tabs ('\t').
62+ */
63+ public static void logSuccess (String user , String operation , String target ,
64+ ApplicationId appId ) {
65+ if (LOG .isInfoEnabled ()) {
66+ LOG .info (createSuccessLog (user , operation , target , appId , null ));
67+ }
68+ }
69+
70+ /**
71+ * Create a readable and parseable audit log string for a successful event.
72+ *
73+ * @param user User who made the service request to the Router
74+ * @param operation Operation requested by the user.
75+ * @param target The target on which the operation is being performed.
76+ * @param appId Application Id in which operation was performed.
77+ * @param subClusterId Subcluster Id in which operation is performed.
78+ *
79+ * <br><br>
80+ * Note that the {@link RouterAuditLogger} uses tabs ('\t') as a key-val
81+ * delimiter and hence the value fields should not contains tabs ('\t').
82+ */
83+ public static void logSuccess (String user , String operation , String target ,
84+ ApplicationId appId , SubClusterId subClusterId ) {
85+ if (LOG .isInfoEnabled ()) {
86+ LOG .info (createSuccessLog (user , operation , target , appId , subClusterId ));
87+ }
88+ }
89+
90+ /**
91+ * A helper api for creating an audit log for a successful event.
92+ */
93+ static String createSuccessLog (String user , String operation , String target ,
94+ ApplicationId appId , SubClusterId subClusterID ) {
95+ StringBuilder b =
96+ createStringBuilderForSuccessEvent (user , operation , target );
97+ if (appId != null ) {
98+ add (Keys .APPID , appId .toString (), b );
99+ }
100+ if (subClusterID != null ) {
101+ add (Keys .SUBCLUSTERID , subClusterID .toString (), b );
102+ }
103+ return b .toString ();
104+ }
105+
106+ /**
107+ * A helper function for creating the common portion of a successful
108+ * log message.
109+ */
110+ private static StringBuilder createStringBuilderForSuccessEvent (String user ,
111+ String operation , String target ) {
112+ StringBuilder b = new StringBuilder ();
113+ start (Keys .USER , user , b );
114+ add (Keys .OPERATION , operation , b );
115+ add (Keys .TARGET , target , b );
116+ add (Keys .RESULT , AuditConstants .SUCCESS , b );
117+ return b ;
118+ }
119+
120+ /**
121+ * Create a readable and parseable audit log string for a failed event.
122+ *
123+ * @param user User who made the service request.
124+ * @param operation Operation requested by the user.
125+ * @param perm Target permissions.
126+ * @param target The target on which the operation is being performed.
127+ * @param description Some additional information as to why the operation
128+ * failed.
129+ *
130+ * <br><br>
131+ * Note that the {@link RouterAuditLogger} uses tabs ('\t') as a key-val
132+ * delimiter and hence the value fields should not contains tabs ('\t').
133+ */
134+ public static void logFailure (String user , String operation , String perm ,
135+ String target , String description ) {
136+ if (LOG .isInfoEnabled ()) {
137+ LOG .info (
138+ createFailureLog (user , operation , perm , target , description , null ,
139+ null ));
140+ }
141+ }
142+
143+ /**
144+ * Create a readable and parseable audit log string for a failed event.
145+ *
146+ * @param user User who made the service request.
147+ * @param operation Operation requested by the user.
148+ * @param perm Target permissions.
149+ * @param target The target on which the operation is being performed.
150+ * @param description Some additional information as to why the operation
151+ * failed.
152+ * @param appId Application Id in which operation was performed.
153+ *
154+ * <br><br>
155+ * Note that the {@link RouterAuditLogger} uses tabs ('\t') as a key-val
156+ * delimiter and hence the value fields should not contains tabs ('\t').
157+ */
158+ public static void logFailure (String user , String operation , String perm ,
159+ String target , String description , ApplicationId appId ) {
160+ if (LOG .isInfoEnabled ()) {
161+ LOG .info (
162+ createFailureLog (user , operation , perm , target , description , appId ,
163+ null ));
164+ }
165+ }
166+
167+ /**
168+ * Create a readable and parseable audit log string for a failed event.
169+ *
170+ * @param user User who made the service request.
171+ * @param operation Operation requested by the user.
172+ * @param perm Target permissions.
173+ * @param target The target on which the operation is being performed.
174+ * @param description Some additional information as to why the operation
175+ * failed.
176+ * @param appId Application Id in which operation was performed.
177+ * @param subClusterId SubCluster Id in which operation was performed.
178+ *
179+ * <br><br>
180+ * Note that the {@link RouterAuditLogger} uses tabs ('\t') as a key-val
181+ * delimiter and hence the value fields should not contains tabs ('\t').
182+ */
183+ public static void logFailure (String user , String operation , String perm ,
184+ String target , String description , ApplicationId appId ,
185+ SubClusterId subClusterId ) {
186+ if (LOG .isInfoEnabled ()) {
187+ LOG .info (
188+ createFailureLog (user , operation , perm , target , description , appId ,
189+ subClusterId ));
190+ }
191+ }
192+
193+ /**
194+ * A helper api for creating an audit log for a failure event.
195+ */
196+ static String createFailureLog (String user , String operation , String perm ,
197+ String target , String description , ApplicationId appId ,
198+ SubClusterId subClusterId ) {
199+ StringBuilder b =
200+ createStringBuilderForFailureLog (user , operation , target , description ,
201+ perm );
202+ if (appId != null ) {
203+ add (Keys .APPID , appId .toString (), b );
204+ }
205+ if (subClusterId != null ) {
206+ add (Keys .SUBCLUSTERID , subClusterId .toString (), b );
207+ }
208+ return b .toString ();
209+ }
210+
211+ /**
212+ * A helper function for creating the common portion of a failure
213+ * log message.
214+ */
215+ private static StringBuilder createStringBuilderForFailureLog (String user ,
216+ String operation , String target , String description , String perm ) {
217+ StringBuilder b = new StringBuilder ();
218+ start (Keys .USER , user , b );
219+ add (Keys .OPERATION , operation , b );
220+ add (Keys .TARGET , target , b );
221+ add (Keys .RESULT , AuditConstants .FAILURE , b );
222+ add (Keys .DESCRIPTION , description , b );
223+ add (Keys .PERMISSIONS , perm , b );
224+ return b ;
225+ }
226+
227+ /**
228+ * Adds the first key-val pair to the passed builder in the following format
229+ * key=value.
230+ */
231+ static void start (Keys key , String value , StringBuilder b ) {
232+ b .append (key .name ()).append (AuditConstants .KEY_VAL_SEPARATOR ).append (value );
233+ }
234+
235+ /**
236+ * Appends the key-val pair to the passed builder in the following format
237+ * <pair-delim>key=value.
238+ */
239+ static void add (Keys key , String value , StringBuilder b ) {
240+ b .append (AuditConstants .PAIR_SEPARATOR ).append (key .name ())
241+ .append (AuditConstants .KEY_VAL_SEPARATOR ).append (value );
242+ }
243+ }
0 commit comments