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