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 */
018package org.apache.hadoop.hbase.security.token;
019
020import com.google.protobuf.ByteString;
021import java.io.DataInput;
022import java.io.DataOutput;
023import java.io.IOException;
024import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
025import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
026import org.apache.hadoop.io.Text;
027import org.apache.hadoop.security.UserGroupInformation;
028import org.apache.hadoop.security.token.TokenIdentifier;
029import org.apache.yetus.audience.InterfaceAudience;
030
031/**
032 * Represents the identity information stored in an HBase authentication token.
033 */
034@InterfaceAudience.Private
035public class AuthenticationTokenIdentifier extends TokenIdentifier {
036  public static final Text AUTH_TOKEN_TYPE = new Text("HBASE_AUTH_TOKEN");
037
038  protected String username;
039  protected int keyId;
040  protected long issueDate;
041  protected long expirationDate;
042  protected long sequenceNumber;
043
044  public AuthenticationTokenIdentifier() {
045  }
046
047  public AuthenticationTokenIdentifier(String username) {
048    this.username = username;
049  }
050
051  public AuthenticationTokenIdentifier(String username, int keyId, long issueDate,
052    long expirationDate) {
053    this.username = username;
054    this.keyId = keyId;
055    this.issueDate = issueDate;
056    this.expirationDate = expirationDate;
057  }
058
059  @Override
060  public Text getKind() {
061    return AUTH_TOKEN_TYPE;
062  }
063
064  @Override
065  public UserGroupInformation getUser() {
066    if (username == null || "".equals(username)) {
067      return null;
068    }
069    return UserGroupInformation.createRemoteUser(username);
070  }
071
072  public String getUsername() {
073    return username;
074  }
075
076  void setUsername(String name) {
077    this.username = name;
078  }
079
080  public int getKeyId() {
081    return keyId;
082  }
083
084  void setKeyId(int id) {
085    this.keyId = id;
086  }
087
088  public long getIssueDate() {
089    return issueDate;
090  }
091
092  void setIssueDate(long timestamp) {
093    this.issueDate = timestamp;
094  }
095
096  public long getExpirationDate() {
097    return expirationDate;
098  }
099
100  void setExpirationDate(long timestamp) {
101    this.expirationDate = timestamp;
102  }
103
104  public long getSequenceNumber() {
105    return sequenceNumber;
106  }
107
108  void setSequenceNumber(long seq) {
109    this.sequenceNumber = seq;
110  }
111
112  public byte[] toBytes() {
113    AuthenticationProtos.TokenIdentifier.Builder builder =
114      AuthenticationProtos.TokenIdentifier.newBuilder();
115    builder.setKind(AuthenticationProtos.TokenIdentifier.Kind.HBASE_AUTH_TOKEN);
116    if (username != null) {
117      builder.setUsername(ByteString.copyFromUtf8(username));
118    }
119    builder.setIssueDate(issueDate).setExpirationDate(expirationDate).setKeyId(keyId)
120      .setSequenceNumber(sequenceNumber);
121    return builder.build().toByteArray();
122  }
123
124  @Override
125  public void write(DataOutput out) throws IOException {
126    byte[] pbBytes = toBytes();
127    out.writeInt(pbBytes.length);
128    out.write(pbBytes);
129  }
130
131  @Override
132  public void readFields(DataInput in) throws IOException {
133    int len = in.readInt();
134    byte[] inBytes = new byte[len];
135    in.readFully(inBytes);
136    AuthenticationProtos.TokenIdentifier.Builder builder =
137      AuthenticationProtos.TokenIdentifier.newBuilder();
138    ProtobufUtil.mergeFrom(builder, inBytes);
139    AuthenticationProtos.TokenIdentifier identifier = builder.build();
140    // sanity check on type
141    if (
142      !identifier.hasKind()
143        || identifier.getKind() != AuthenticationProtos.TokenIdentifier.Kind.HBASE_AUTH_TOKEN
144    ) {
145      throw new IOException("Invalid TokenIdentifier kind from input " + identifier.getKind());
146    }
147
148    // copy the field values
149    if (identifier.hasUsername()) {
150      username = identifier.getUsername().toStringUtf8();
151    }
152    if (identifier.hasKeyId()) {
153      keyId = identifier.getKeyId();
154    }
155    if (identifier.hasIssueDate()) {
156      issueDate = identifier.getIssueDate();
157    }
158    if (identifier.hasExpirationDate()) {
159      expirationDate = identifier.getExpirationDate();
160    }
161    if (identifier.hasSequenceNumber()) {
162      sequenceNumber = identifier.getSequenceNumber();
163    }
164  }
165
166  @Override
167  public boolean equals(Object other) {
168    if (other == null) {
169      return false;
170    }
171    if (other instanceof AuthenticationTokenIdentifier) {
172      AuthenticationTokenIdentifier ident = (AuthenticationTokenIdentifier) other;
173      return sequenceNumber == ident.getSequenceNumber() && keyId == ident.getKeyId()
174        && issueDate == ident.getIssueDate() && expirationDate == ident.getExpirationDate()
175        && (username == null ? ident.getUsername() == null : username.equals(ident.getUsername()));
176    }
177    return false;
178  }
179
180  @Override
181  public int hashCode() {
182    return (int) sequenceNumber;
183  }
184
185  @Override
186  public String toString() {
187    return "(username=" + username + ", keyId=" + keyId + ", issueDate=" + issueDate
188      + ", expirationDate=" + expirationDate + ", sequenceNumber=" + sequenceNumber + ")";
189  }
190}