-
Notifications
You must be signed in to change notification settings - Fork 588
HDDS-8829. Symmetric Keys for Delegation Tokens #7394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9a6093b
74a8432
3649530
1afacb0
e96c28a
32fa80e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,12 +23,14 @@ | |||||||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||||||||
| import java.time.Instant; | ||||||||||||||||||||||||||
| import java.util.Arrays; | ||||||||||||||||||||||||||
| import java.util.UUID; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import com.google.common.base.Preconditions; | ||||||||||||||||||||||||||
| import org.apache.commons.lang3.StringUtils; | ||||||||||||||||||||||||||
| import org.apache.commons.lang3.builder.EqualsBuilder; | ||||||||||||||||||||||||||
| import org.apache.hadoop.hdds.annotation.InterfaceAudience; | ||||||||||||||||||||||||||
| import org.apache.hadoop.hdds.annotation.InterfaceStability; | ||||||||||||||||||||||||||
| import org.apache.hadoop.io.DataInputBuffer; | ||||||||||||||||||||||||||
| import org.apache.hadoop.io.DataOutputBuffer; | ||||||||||||||||||||||||||
| import org.apache.hadoop.io.Text; | ||||||||||||||||||||||||||
| import org.apache.hadoop.io.WritableUtils; | ||||||||||||||||||||||||||
| import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMTokenProto; | ||||||||||||||||||||||||||
|
|
@@ -47,7 +49,11 @@ public class OzoneTokenIdentifier extends | |||||||||||||||||||||||||
| AbstractDelegationTokenIdentifier { | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| public static final Text KIND_NAME = new Text("OzoneToken"); | ||||||||||||||||||||||||||
| @Deprecated | ||||||||||||||||||||||||||
| // the certificate id of this OM, deprecated since HDDS-8829 | ||||||||||||||||||||||||||
| private String omCertSerialId; | ||||||||||||||||||||||||||
| // shared secret key id generated by SCM. | ||||||||||||||||||||||||||
| private String secretKeyId; | ||||||||||||||||||||||||||
| private Type tokenType; | ||||||||||||||||||||||||||
| private String awsAccessId; | ||||||||||||||||||||||||||
| private String signature; | ||||||||||||||||||||||||||
|
|
@@ -82,31 +88,6 @@ public Text getKind() { | |||||||||||||||||||||||||
| return KIND_NAME; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /** Instead of relying on proto serialization, this | ||||||||||||||||||||||||||
| * provides explicit serialization for OzoneTokenIdentifier. | ||||||||||||||||||||||||||
| * @return byte[] | ||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||
| public byte[] toUniqueSerializedKey() { | ||||||||||||||||||||||||||
| DataOutputBuffer buf = new DataOutputBuffer(); | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| super.write(buf); | ||||||||||||||||||||||||||
| WritableUtils.writeVInt(buf, getTokenType().getNumber()); | ||||||||||||||||||||||||||
| // Set s3 specific fields. | ||||||||||||||||||||||||||
| if (getTokenType().equals(S3AUTHINFO)) { | ||||||||||||||||||||||||||
| WritableUtils.writeString(buf, getAwsAccessId()); | ||||||||||||||||||||||||||
| WritableUtils.writeString(buf, getSignature()); | ||||||||||||||||||||||||||
| WritableUtils.writeString(buf, getStrToSign()); | ||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| WritableUtils.writeString(buf, getOmCertSerialId()); | ||||||||||||||||||||||||||
| WritableUtils.writeString(buf, getOmServiceId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } catch (java.io.IOException e) { | ||||||||||||||||||||||||||
| throw new IllegalArgumentException( | ||||||||||||||||||||||||||
| "Can't encode the the raw data ", e); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return buf.getData(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /** Instead of relying on proto deserialization, this | ||||||||||||||||||||||||||
| * provides explicit deserialization for OzoneTokenIdentifier. | ||||||||||||||||||||||||||
| * @return byte[] | ||||||||||||||||||||||||||
|
|
@@ -125,20 +106,19 @@ public OzoneTokenIdentifier fromUniqueSerializedKey(byte[] rawData) | |||||||||||||||||||||||||
| setStrToSign(WritableUtils.readString(in)); | ||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| this.tokenType = Type.DELEGATION_TOKEN; | ||||||||||||||||||||||||||
| setOmCertSerialId(WritableUtils.readString(in)); | ||||||||||||||||||||||||||
| String value = WritableUtils.readString(in); | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| UUID.fromString(value); | ||||||||||||||||||||||||||
| setSecretKeyId(value); | ||||||||||||||||||||||||||
| } catch (IllegalArgumentException e) { | ||||||||||||||||||||||||||
| setOmCertSerialId(value); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+110
to
+115
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using exception handling for this case is probably going to be expensive.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh wait this is not right. Why does it call UUID.fromString() and ignore the return value?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because this OzoneTokenIdentifier#toUniqueSerializedKey uses its own raw format instead of OMTokenProto format, which I have no idea why. In a period of time(7d, max delegation time lifetime) after OM is upgraded to use shared secret key, the same index string would be cerial ID or secreKey ID. So this " UUID.fromString(value);" used to detect whether it's secretKey, which is a UUID, or a serial ID, which is a number. Let me further check if we can refactor some existing code, to avoid this UUID.fromString(value) being executed after upgrade 7days.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was going to suggest to use Integer.isNumeric(). But it throws an exception internally so it ends up the same. |
||||||||||||||||||||||||||
| setOmServiceId(WritableUtils.readString(in)); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return this; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||
| * Overrides default implementation to write using Protobuf. | ||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||
| * @param out output stream | ||||||||||||||||||||||||||
| * @throws IOException | ||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||
| public void write(DataOutput out) throws IOException { | ||||||||||||||||||||||||||
| public OMTokenProto toProtoBuf() throws IOException { | ||||||||||||||||||||||||||
| OMTokenProto.Builder builder = OMTokenProto.newBuilder() | ||||||||||||||||||||||||||
| .setMaxDate(getMaxDate()) | ||||||||||||||||||||||||||
| .setType(getTokenType()) | ||||||||||||||||||||||||||
|
|
@@ -155,14 +135,28 @@ public void write(DataOutput out) throws IOException { | |||||||||||||||||||||||||
| .setSignature(getSignature()) | ||||||||||||||||||||||||||
| .setStrToSign(getStrToSign()); | ||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| builder.setOmCertSerialId(getOmCertSerialId()); | ||||||||||||||||||||||||||
| if (StringUtils.isNotEmpty(getOmCertSerialId())) { | ||||||||||||||||||||||||||
| builder.setOmCertSerialId(getOmCertSerialId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (StringUtils.isNotEmpty(getSecretKeyId())) { | ||||||||||||||||||||||||||
| builder.setSecretKeyId(getSecretKeyId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (getOmServiceId() != null) { | ||||||||||||||||||||||||||
| builder.setOmServiceId(getOmServiceId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return builder.build(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| OMTokenProto token = builder.build(); | ||||||||||||||||||||||||||
| out.write(token.toByteArray()); | ||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||
| * Overrides default implementation to write using Protobuf. | ||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||
| * @param out output stream | ||||||||||||||||||||||||||
| * @throws IOException | ||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||
| public void write(DataOutput out) throws IOException { | ||||||||||||||||||||||||||
| out.write(toProtoBuf().toByteArray()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||
|
|
@@ -183,7 +177,12 @@ public void readFields(DataInput in) throws IOException { | |||||||||||||||||||||||||
| setMaxDate(token.getMaxDate()); | ||||||||||||||||||||||||||
| setSequenceNumber(token.getSequenceNumber()); | ||||||||||||||||||||||||||
| setMasterKeyId(token.getMasterKeyId()); | ||||||||||||||||||||||||||
| setOmCertSerialId(token.getOmCertSerialId()); | ||||||||||||||||||||||||||
| if (token.hasOmCertSerialId()) { | ||||||||||||||||||||||||||
| setOmCertSerialId(token.getOmCertSerialId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (token.hasSecretKeyId()) { | ||||||||||||||||||||||||||
| setSecretKeyId(token.getSecretKeyId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // Set s3 specific fields. | ||||||||||||||||||||||||||
| if (getTokenType().equals(S3AUTHINFO)) { | ||||||||||||||||||||||||||
|
|
@@ -221,7 +220,12 @@ public static OzoneTokenIdentifier readProtoBuf(DataInput in) | |||||||||||||||||||||||||
| identifier.setSequenceNumber(token.getSequenceNumber()); | ||||||||||||||||||||||||||
| identifier.setMasterKeyId(token.getMasterKeyId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| identifier.setOmCertSerialId(token.getOmCertSerialId()); | ||||||||||||||||||||||||||
| if (token.hasOmCertSerialId()) { | ||||||||||||||||||||||||||
| identifier.setOmCertSerialId(token.getOmCertSerialId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (token.hasSecretKeyId()) { | ||||||||||||||||||||||||||
| identifier.setSecretKeyId(token.getSecretKeyId()); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| identifier.setOmServiceId(token.getOmServiceId()); | ||||||||||||||||||||||||||
| return identifier; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
@@ -264,6 +268,7 @@ public boolean equals(Object obj) { | |||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| OzoneTokenIdentifier that = (OzoneTokenIdentifier) obj; | ||||||||||||||||||||||||||
| return new EqualsBuilder() | ||||||||||||||||||||||||||
| .append(getSecretKeyId(), that.getSecretKeyId()) | ||||||||||||||||||||||||||
| .append(getOmCertSerialId(), that.getOmCertSerialId()) | ||||||||||||||||||||||||||
| .append(getMaxDate(), that.getMaxDate()) | ||||||||||||||||||||||||||
| .append(getIssueDate(), that.getIssueDate()) | ||||||||||||||||||||||||||
|
|
@@ -326,6 +331,18 @@ public String getOmCertSerialId() { | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| public void setOmCertSerialId(String omCertSerialId) { | ||||||||||||||||||||||||||
| this.omCertSerialId = omCertSerialId; | ||||||||||||||||||||||||||
| Preconditions.checkArgument(this.omCertSerialId == null || this.secretKeyId == null, | ||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this would not validate it. Imagine you have
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The check here is to make sure a OzoneTokenIdentifier cannot have both omCertSerialId and secretKeyId set. It can only have one of them. |
||||||||||||||||||||||||||
| "omCertSerialId and secretKeyId cannot both be valid"); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| public String getSecretKeyId() { | ||||||||||||||||||||||||||
| return secretKeyId; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| public void setSecretKeyId(String id) { | ||||||||||||||||||||||||||
| this.secretKeyId = id; | ||||||||||||||||||||||||||
| Preconditions.checkArgument(this.omCertSerialId == null || this.secretKeyId == null, | ||||||||||||||||||||||||||
| "omCertSerialId and secretKeyId cannot both be valid"); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| public String getOmServiceId() { | ||||||||||||||||||||||||||
|
|
@@ -383,7 +400,8 @@ public String toString() { | |||||||||||||||||||||||||
| .append(", signature=").append(getSignature()) | ||||||||||||||||||||||||||
| .append(", awsAccessKeyId=").append(getAwsAccessId()) | ||||||||||||||||||||||||||
| .append(", omServiceId=").append(getOmServiceId()) | ||||||||||||||||||||||||||
| .append(", omCertSerialId=").append(getOmCertSerialId()); | ||||||||||||||||||||||||||
| .append(", omCertSerialId=").append(getOmCertSerialId()) | ||||||||||||||||||||||||||
| .append(", secretKeyId=").append(getSecretKeyId()); | ||||||||||||||||||||||||||
| return buffer.toString(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1457,7 +1457,8 @@ message OMTokenProto { | |
| optional string accessKeyId = 12; | ||
| optional string signature = 13; | ||
| optional string strToSign = 14; | ||
| optional string omServiceId = 15; | ||
| optional string omServiceId = 15 [deprecated = true]; | ||
| optional string secretKeyId = 16; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deprecated
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right |
||
| } | ||
|
|
||
| message SecretKeyProto { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before this patch, secretKey service only starts when block token or container token is enabled. With this patch, secretKey should start only when security is enabled, for delegation token is by default enabled when security is enabled.