001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.security.access; 020 021import java.util.Collection; 022import java.util.HashMap; 023import java.util.Map; 024import java.util.Map.Entry; 025 026import org.apache.yetus.audience.InterfaceAudience; 027import org.apache.hadoop.hbase.Cell; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.security.User; 030import org.apache.hadoop.hbase.util.Bytes; 031 032import org.apache.hbase.thirdparty.com.google.common.base.Joiner; 033 034/** 035 * Represents the result of an authorization check for logging and error 036 * reporting. 037 */ 038@InterfaceAudience.Private 039public class AuthResult { 040 private boolean allowed; 041 private final String namespace; 042 private final TableName table; 043 private final Permission.Action action; 044 private final String request; 045 private String reason; 046 private final User user; 047 private AuthResult.Params params; 048 049 // "family" and "qualifier" should only be used if "families" is null. 050 private final byte[] family; 051 private final byte[] qualifier; 052 private final Map<byte[], ? extends Collection<?>> families; 053 054 public AuthResult(boolean allowed, String request, String reason, User user, 055 Permission.Action action, TableName table, byte[] family, byte[] qualifier) { 056 this.allowed = allowed; 057 this.request = request; 058 this.reason = reason; 059 this.user = user; 060 this.table = table; 061 this.family = family; 062 this.qualifier = qualifier; 063 this.action = action; 064 this.families = null; 065 this.namespace = null; 066 this.params = new Params().setTableName(table).setFamily(family).setQualifier(qualifier); 067 } 068 069 public AuthResult(boolean allowed, String request, String reason, User user, 070 Permission.Action action, TableName table, 071 Map<byte[], ? extends Collection<?>> families) { 072 this.allowed = allowed; 073 this.request = request; 074 this.reason = reason; 075 this.user = user; 076 this.table = table; 077 this.family = null; 078 this.qualifier = null; 079 this.action = action; 080 this.families = families; 081 this.namespace = null; 082 this.params = new Params().setTableName(table).setFamilies(families); 083 } 084 085 public AuthResult(boolean allowed, String request, String reason, User user, 086 Permission.Action action, String namespace) { 087 this.allowed = allowed; 088 this.request = request; 089 this.reason = reason; 090 this.user = user; 091 this.namespace = namespace; 092 this.action = action; 093 this.table = null; 094 this.family = null; 095 this.qualifier = null; 096 this.families = null; 097 this.params = new Params().setNamespace(namespace); 098 } 099 100 public boolean isAllowed() { 101 return allowed; 102 } 103 104 public User getUser() { 105 return user; 106 } 107 108 public String getReason() { 109 return reason; 110 } 111 112 public TableName getTableName() { 113 return table; 114 } 115 116 public byte[] getFamily() { 117 return family; 118 } 119 120 public byte[] getQualifier() { 121 return qualifier; 122 } 123 124 public Permission.Action getAction() { 125 return action; 126 } 127 128 public String getRequest() { 129 return request; 130 } 131 132 public Params getParams() { return this.params;} 133 134 public void setAllowed(boolean allowed) { 135 this.allowed = allowed; 136 } 137 138 public void setReason(String reason) { 139 this.reason = reason; 140 } 141 142 private static String toFamiliesString(Map<byte[], ? extends Collection<?>> families, 143 byte[] family, byte[] qual) { 144 StringBuilder sb = new StringBuilder(); 145 if (families != null) { 146 boolean first = true; 147 for (Map.Entry<byte[], ? extends Collection<?>> entry : families.entrySet()) { 148 String familyName = Bytes.toString(entry.getKey()); 149 if (entry.getValue() != null && !entry.getValue().isEmpty()) { 150 for (Object o : entry.getValue()) { 151 String qualifier; 152 if (o instanceof byte[]) { 153 qualifier = Bytes.toString((byte[])o); 154 } else if (o instanceof Cell) { 155 Cell c = (Cell) o; 156 qualifier = Bytes.toString(c.getQualifierArray(), c.getQualifierOffset(), 157 c.getQualifierLength()); 158 } else { 159 // Shouldn't really reach this? 160 qualifier = o.toString(); 161 } 162 if (!first) { 163 sb.append("|"); 164 } 165 first = false; 166 sb.append(familyName).append(":").append(qualifier); 167 } 168 } else { 169 if (!first) { 170 sb.append("|"); 171 } 172 first = false; 173 sb.append(familyName); 174 } 175 } 176 } else if (family != null) { 177 sb.append(Bytes.toString(family)); 178 if (qual != null) { 179 sb.append(":").append(Bytes.toString(qual)); 180 } 181 } 182 return sb.toString(); 183 } 184 185 public String toContextString() { 186 StringBuilder sb = new StringBuilder(); 187 String familiesString = toFamiliesString(families, family, qualifier); 188 sb.append("(user=") 189 .append(user != null ? user.getName() : "UNKNOWN") 190 .append(", "); 191 sb.append("scope=") 192 .append(namespace != null ? namespace : 193 table == null ? "GLOBAL" : table.getNameWithNamespaceInclAsString()) 194 .append(", "); 195 if(namespace == null && familiesString.length() > 0) { 196 sb.append("family=") 197 .append(familiesString) 198 .append(", "); 199 } 200 String paramsString = params.toString(); 201 if(paramsString.length() > 0) { 202 sb.append("params=[") 203 .append(paramsString) 204 .append("],"); 205 } 206 sb.append("action=") 207 .append(action != null ? action.toString() : "") 208 .append(")"); 209 return sb.toString(); 210 } 211 212 @Override 213 public String toString() { 214 return "AuthResult" + toContextString(); 215 } 216 217 public static AuthResult allow(String request, String reason, User user, 218 Permission.Action action, String namespace) { 219 return new AuthResult(true, request, reason, user, action, namespace); 220 } 221 222 public static AuthResult allow(String request, String reason, User user, 223 Permission.Action action, TableName table, byte[] family, byte[] qualifier) { 224 return new AuthResult(true, request, reason, user, action, table, family, qualifier); 225 } 226 227 public static AuthResult allow(String request, String reason, User user, 228 Permission.Action action, TableName table, 229 Map<byte[], ? extends Collection<?>> families) { 230 return new AuthResult(true, request, reason, user, action, table, families); 231 } 232 233 public static AuthResult deny(String request, String reason, User user, 234 Permission.Action action, String namespace) { 235 return new AuthResult(false, request, reason, user, action, namespace); 236 } 237 238 public static AuthResult deny(String request, String reason, User user, 239 Permission.Action action, TableName table, byte[] family, byte[] qualifier) { 240 return new AuthResult(false, request, reason, user, action, table, family, qualifier); 241 } 242 243 public static AuthResult deny(String request, String reason, User user, 244 Permission.Action action, TableName table, 245 Map<byte[], ? extends Collection<?>> families) { 246 return new AuthResult(false, request, reason, user, action, table, families); 247 } 248 249 public String toFamilyString() { 250 return toFamiliesString(families, family, qualifier); 251 } 252 253 public static class Params { 254 private String namespace = null; 255 private TableName tableName = null; 256 private Map<byte[], ? extends Collection<?>> families = null; 257 byte[] family = null; 258 byte[] qualifier = null; 259 // For extra parameters to be shown in audit log 260 private final Map<String, String> extraParams = new HashMap<String, String>(2); 261 262 public Params addExtraParam(String key, String value) { 263 extraParams.put(key, value); 264 return this; 265 } 266 267 public Params setNamespace(String namespace) { 268 this.namespace = namespace; 269 return this; 270 } 271 272 public Params setTableName(TableName table) { 273 this.tableName = table; 274 return this; 275 } 276 277 public Params setFamilies(Map<byte[], ? extends Collection<?>> families) { 278 this.families = families; 279 return this; 280 } 281 282 public Params setFamily(byte[] family) { 283 this.family = family; 284 return this; 285 } 286 287 public Params setQualifier(byte[] qualifier) { 288 this.qualifier = qualifier; 289 return this; 290 } 291 292 @Override 293 public String toString() { 294 String familiesString = toFamiliesString(families, family, qualifier); 295 String[] params = new String[] { 296 namespace != null ? "namespace=" + namespace : null, 297 tableName != null ? "table=" + tableName.getNameWithNamespaceInclAsString() : null, 298 familiesString.length() > 0 ? "family=" + familiesString : null, 299 extraParams.isEmpty() ? null : concatenateExtraParams() 300 }; 301 return Joiner.on(",").skipNulls().join(params); 302 } 303 304 /** 305 * @return extra parameter key/value string 306 */ 307 private String concatenateExtraParams() { 308 final StringBuilder sb = new StringBuilder(); 309 boolean first = true; 310 for (Entry<String, String> entry : extraParams.entrySet()) { 311 if (entry.getKey() != null && entry.getValue() != null) { 312 if (!first) { 313 sb.append(','); 314 } 315 first = false; 316 sb.append(entry.getKey() + '='); 317 sb.append(entry.getValue()); 318 } 319 } 320 return sb.toString(); 321 } 322 } 323}