Project

General

Profile

Actions

Bug #23831

open

bucket policy ipdeny not in effect

Added by Amine Liu almost 6 years ago. Updated almost 6 years ago.

Status:
Triaged
Priority:
Normal
Category:
-
Target version:
% Done:

0%

Source:
Tags:
Backport:
Regression:
No
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
rgw
Pull request ID:
Crash signature (v1):
Crash signature (v2):

Description

I set bucket policy ipdeny, but still can read and write objects; but only set versioning will return 403;

Actions #1

Updated by Matt Benjamin almost 6 years ago

  • Status changed from New to Triaged
  • Assignee set to Pritha Srivastava

@tave, could you provide detailed reproducer information--i.e., the policy you applied, and what you applied it to?

Matt

Actions #2

Updated by Amine Liu almost 6 years ago

{
"Statement": [ {
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Resource": "arn:aws:s3:::test1",
"Condition": {
"IpAddress": {
"aws:SourceIp": "172.26.218.0/22"
}
}
}
]
}

I set this policy to bucket test1, but still can get/remove this policy on ip 192.168.xx.xx

Actions #3

Updated by Amine Liu almost 6 years ago

{
"Statement": [ {
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::test1/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "192.168.0.0/16"
}
}
}
]
}

and I set this policy, but can put/rm bucket test1's objects on 172.26.xx.xx;
and return 403 when `s3cmd info s3://test1/xxx

Actions #4

Updated by Pritha Srivastava almost 6 years ago

Hi @Tave - Do you want to block PutBucketPolicy and other actions if the request is coming from SourceIp - "172.26.218.0/22" or "192.168.0.0/16", then you need to set the Effect to 'Deny' and Condition with IpAddress set to "172.26.218.0/22"or "192.168.0.0/16" like:

"Statement": [ {
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Resource": "arn:aws:s3:::test1",
"Condition": {
"IpAddress": {
"aws:SourceIp": "172.26.218.0/22"
}
}
}
]
}

Let me know if this works for you?

Actions #5

Updated by Amine Liu almost 6 years ago

Pritha Srivastava wrote:

Hi @Tave - Do you want to block PutBucketPolicy and other actions if the request is coming from SourceIp - "172.26.218.0/22" or "192.168.0.0/16", then you need to set the Effect to 'Deny' and Condition with IpAddress set to "172.26.218.0/22"or "192.168.0.0/16" like:

"Statement": [ {
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Resource": "arn:aws:s3:::test1",
"Condition": {
"IpAddress": {
"aws:SourceIp": "172.26.218.0/22"
}
}
}
]
}

Let me know if this works for you?

No, not works well. I can delpolicy on 172.26.218.0/22

Actions #6

Updated by Amine Liu almost 6 years ago

Tave liu wrote:

Pritha Srivastava wrote:

Hi @Tave - Do you want to block PutBucketPolicy and other actions if the request is coming from SourceIp - "172.26.218.0/22" or "192.168.0.0/16", then you need to set the Effect to 'Deny' and Condition with IpAddress set to "172.26.218.0/22"or "192.168.0.0/16" like:

"Statement": [ {
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Resource": "arn:aws:s3:::test1",
"Condition": {
"IpAddress": {
"aws:SourceIp": "172.26.218.0/22"
}
}
}
]
}

Let me know if this works for you?

No, not works well. I can delpolicy on 172.26.218.0/22 ,and can delpolicy on 192.168.xx.xx

Actions #7

Updated by Pritha Srivastava almost 6 years ago

Hi @Tave,

I tried the above policy on my system and it works for me i.e. If I set the Effect to 'Deny' and Action to 'DeleteBucketPolicy' for a particular IP Address, it works fine for me. I have some questions for you:

1. Do you have a reverse proxy in your set-up?
2. Can you give some more details of the steps that you performed and the exact policy that you used?
3. For the DeleteBucketPolicy operation can you check the value of REMOTE_ADDR in the logs and add it here, or can you upload the logs here?

Actions #8

Updated by Amine Liu almost 6 years ago

[root@gz-sx4f-oss2-01 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 80:41:26:81:c7:07 brd ff:ff:ff:ff:ff:ff
inet 172.26.218.1/27 brd 172.26.218.31 scope global eth0
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP qlen 1000
link/ether 80:41:26:81:c7:08 brd ff:ff:ff:ff:ff:ff
inet 172.26.226.1/27 brd 172.26.226.31 scope global eth1
valid_lft forever preferred_lft forever

[root@gz-sx4f-oss2-01 ~]# s3cmd -c test.cfg info s3://test3f
s3://test3f/ (bucket):
Location: testgroup
Payer: BucketOwner
Expiration Rule: none
Policy: {"Statement": [{
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Resource": "arn:aws:s3:::test1",
"Condition": {
"IpAddress": {
"aws:SourceIp": "172.26.218.0/22"
}
}
}]
}

CORS:      none
ACL: test1: FULL_CONTROL
[root@gz-sx4f-oss2-01 ~]#
[root@gz-sx4f-oss2-01 ~]# s3cmd c test.cfg delpolicy s3://test3f -d
DEBUG: s3cmd version 2.0.1
DEBUG: ConfigParser: Reading file 'test.cfg'
DEBUG: ConfigParser: user
>test1
DEBUG: ConfigParser: access_key->E7...17_chars...W
DEBUG: ConfigParser: secret_key->te...3_chars...
DEBUG: ConfigParser: host_base->test3f.imu.cn
DEBUG: ConfigParser: host_bucket->test3f.imu.cn/%(bucket)
DEBUG: ConfigParser: use_https->False
DEBUG: Updating Config.Config cache_file ->
DEBUG: Updating Config.Config follow_symlinks -> False
DEBUG: Updating Config.Config verbosity -> 10
DEBUG: Unicodising 'delpolicy' using UTF-8
DEBUG: Unicodising 's3://test3f' using UTF-8
DEBUG: Command: delpolicy
DEBUG: CreateRequest: resource[uri]=/
DEBUG: delete_policy(s3://test3f/)
DEBUG: ===== Send_request inner request to determine the bucket region =====
DEBUG: CreateRequest: resource[uri]=/
DEBUG: Using signature v4
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: canonical_headers = host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

DEBUG: Canonical Request:
GET
/
location=
host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

host;x-amz-content-sha256;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
----------------------
DEBUG: signature-v4 headers: {'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=f6ba94f30326de128b83b49221ff333bb47a83f0e5cb2d37e5b99701b02c61c7', 'x-amz-date': '20180509T065225Z'}
DEBUG: Processing request, please wait...
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: ConnMan.get(): creating new connection: http://test3f.imu.cn
DEBUG: non-proxied HTTPConnection(test3f.imu.cn, None)
DEBUG: format_uri(): /?location
DEBUG: Sending request method_string='GET', uri=u'/?location', headers={'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=f6ba94f30326de128b83b49221ff333bb47a83f0e5cb2d37e5b99701b02c61c7', 'x-amz-date': '20180509T065225Z'}, body=(0 bytes)
DEBUG: ConnMan.put(): connection put back to pool (http://test3f.imu.cn#1)
DEBUG: Response: {'data': '<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/&quot;&gt;&lt;Owner&gt;&lt;ID&gt;test1&lt;/ID&gt;&lt;DisplayName&gt;test1&lt;/DisplayName&gt;&lt;/Owner&gt;&lt;Buckets&gt;&lt;Bucket&gt;&lt;Name&gt;test3f&lt;/Name&gt;&lt;CreationDate&gt;2018-05-07T03:32:12.711Z&lt;/CreationDate&gt;&lt;/Bucket&gt;&lt;Bucket&gt;&lt;Name&gt;test4f&lt;/Name&gt;&lt;CreationDate&gt;2018-05-07T03:42:50.952Z&lt;/CreationDate&gt;&lt;/Bucket&gt;&lt;/Buckets&gt;&lt;/ListAllMyBucketsResult&gt;',
'headers': {'content-length': '393',
'content-type': 'application/xml',
'date': 'Wed, 09 May 2018 06:52:24 GMT',
'x-amz-request-id': 'tx0000000000000001af930-005af29aa8-5fa1-test3f'},
'reason': 'OK',
'status': 200}
DEBUG: ===== END send_request inner request to determine the bucket region ('us-east-1') =====
DEBUG: Using signature v4
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: canonical_headers = host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

DEBUG: Canonical Request:
DELETE
/test3f/
policy=
host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

host;x-amz-content-sha256;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
----------------------
DEBUG: signature-v4 headers: {'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=2602b0d42cee4598fadb514f0011ac13da9cadecf6202e0fbecb0cc7369e25f6', 'x-amz-date': '20180509T065225Z'}
DEBUG: Processing request, please wait...
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: ConnMan.get(): re-using connection: http://test3f.imu.cn#1
DEBUG: format_uri(): /test3f/?policy
DEBUG: Sending request method_string='DELETE', uri=u'/test3f/?policy', headers={'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=2602b0d42cee4598fadb514f0011ac13da9cadecf6202e0fbecb0cc7369e25f6', 'x-amz-date': '20180509T065225Z'}, body=(0 bytes)
DEBUG: ConnMan.put(): connection put back to pool (http://test3f.imu.cn#2)
DEBUG: Response: {'data': '',
'headers': {'content-length': '0',
'date': 'Wed, 09 May 2018 06:52:24 GMT',
'x-amz-request-id': 'tx0000000000000001af931-005af29aa8-5fa1-test3f'},
'reason': 'OK',
'status': 200}
DEBUG: response - 200
s3://test3f/: Policy deleted
[root@gz-sx4f-oss2-01 ~]#
[root@gz-sx4f-oss2-01 ~]# s3cmd -c test.cfg info s3://test3f
s3://test3f/ (bucket):
Location: testgroup
Payer: BucketOwner
Expiration Rule: none
Policy: none
CORS: none
ACL: test1: FULL_CONTROL
[root@gz-sx4f-oss2-01 ~]#

Actions #9

Updated by Pritha Srivastava almost 6 years ago

Tave liu wrote:

[root@gz-sx4f-oss2-01 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 80:41:26:81:c7:07 brd ff:ff:ff:ff:ff:ff
inet 172.26.218.1/27 brd 172.26.218.31 scope global eth0
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP qlen 1000
link/ether 80:41:26:81:c7:08 brd ff:ff:ff:ff:ff:ff
inet 172.26.226.1/27 brd 172.26.226.31 scope global eth1
valid_lft forever preferred_lft forever

[root@gz-sx4f-oss2-01 ~]# s3cmd -c test.cfg info s3://test3f
s3://test3f/ (bucket):
Location: testgroup
Payer: BucketOwner
Expiration Rule: none
Policy: {"Statement": [{
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Resource": "arn:aws:s3:::test1",
"Condition": {
"IpAddress": {
"aws:SourceIp": "172.26.218.0/22"
}
}
}]
}

CORS: none
ACL: test1: FULL_CONTROL
[root@gz-sx4f-oss2-01 ~]#
[root@gz-sx4f-oss2-01 ~]# s3cmd c test.cfg delpolicy s3://test3f -d
DEBUG: s3cmd version 2.0.1
DEBUG: ConfigParser: Reading file 'test.cfg'
DEBUG: ConfigParser: user
>test1
DEBUG: ConfigParser: access_key->E7...17_chars...W
DEBUG: ConfigParser: secret_key->te...3_chars...
DEBUG: ConfigParser: host_base->test3f.imu.cn
DEBUG: ConfigParser: host_bucket->test3f.imu.cn/%(bucket)
DEBUG: ConfigParser: use_https->False
DEBUG: Updating Config.Config cache_file ->
DEBUG: Updating Config.Config follow_symlinks -> False
DEBUG: Updating Config.Config verbosity -> 10
DEBUG: Unicodising 'delpolicy' using UTF-8
DEBUG: Unicodising 's3://test3f' using UTF-8
DEBUG: Command: delpolicy
DEBUG: CreateRequest: resource[uri]=/
DEBUG: delete_policy(s3://test3f/)
DEBUG: ===== Send_request inner request to determine the bucket region =====
DEBUG: CreateRequest: resource[uri]=/
DEBUG: Using signature v4
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: canonical_headers = host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

DEBUG: Canonical Request:
GET
/
location=
host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

host;x-amz-content-sha256;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
----------------------
DEBUG: signature-v4 headers: {'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=f6ba94f30326de128b83b49221ff333bb47a83f0e5cb2d37e5b99701b02c61c7', 'x-amz-date': '20180509T065225Z'}
DEBUG: Processing request, please wait...
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: ConnMan.get(): creating new connection: http://test3f.imu.cn
DEBUG: non-proxied HTTPConnection(test3f.imu.cn, None)
DEBUG: format_uri(): /?location
DEBUG: Sending request method_string='GET', uri=u'/?location', headers={'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=f6ba94f30326de128b83b49221ff333bb47a83f0e5cb2d37e5b99701b02c61c7', 'x-amz-date': '20180509T065225Z'}, body=(0 bytes)
DEBUG: ConnMan.put(): connection put back to pool (http://test3f.imu.cn#1)
DEBUG: Response: {'data': '<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/&quot;&gt;&lt;Owner&gt;&lt;ID&gt;test1&lt;/ID&gt;&lt;DisplayName&gt;test1&lt;/DisplayName&gt;&lt;/Owner&gt;&lt;Buckets&gt;&lt;Bucket&gt;&lt;Name&gt;test3f&lt;/Name&gt;&lt;CreationDate&gt;2018-05-07T03:32:12.711Z&lt;/CreationDate&gt;&lt;/Bucket&gt;&lt;Bucket&gt;&lt;Name&gt;test4f&lt;/Name&gt;&lt;CreationDate&gt;2018-05-07T03:42:50.952Z&lt;/CreationDate&gt;&lt;/Bucket&gt;&lt;/Buckets&gt;&lt;/ListAllMyBucketsResult&gt;',
'headers': {'content-length': '393',
'content-type': 'application/xml',
'date': 'Wed, 09 May 2018 06:52:24 GMT',
'x-amz-request-id': 'tx0000000000000001af930-005af29aa8-5fa1-test3f'},
'reason': 'OK',
'status': 200}
DEBUG: ===== END send_request inner request to determine the bucket region ('us-east-1') =====
DEBUG: Using signature v4
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: canonical_headers = host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

DEBUG: Canonical Request:
DELETE
/test3f/
policy=
host:test3f.imu.cn
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20180509T065225Z

host;x-amz-content-sha256;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
----------------------
DEBUG: signature-v4 headers: {'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=2602b0d42cee4598fadb514f0011ac13da9cadecf6202e0fbecb0cc7369e25f6', 'x-amz-date': '20180509T065225Z'}
DEBUG: Processing request, please wait...
DEBUG: get_hostname(test3f): test3f.imu.cn
DEBUG: ConnMan.get(): re-using connection: http://test3f.imu.cn#1
DEBUG: format_uri(): /test3f/?policy
DEBUG: Sending request method_string='DELETE', uri=u'/test3f/?policy', headers={'x-amz-content-sha256': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Authorization': u'AWS4-HMAC-SHA256 Credential=E7WJKMAZ6F54ES92FYXW/20180509/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=2602b0d42cee4598fadb514f0011ac13da9cadecf6202e0fbecb0cc7369e25f6', 'x-amz-date': '20180509T065225Z'}, body=(0 bytes)
DEBUG: ConnMan.put(): connection put back to pool (http://test3f.imu.cn#2)
DEBUG: Response: {'data': '',
'headers': {'content-length': '0',
'date': 'Wed, 09 May 2018 06:52:24 GMT',
'x-amz-request-id': 'tx0000000000000001af931-005af29aa8-5fa1-test3f'},
'reason': 'OK',
'status': 200}
DEBUG: response - 200
s3://test3f/: Policy deleted
[root@gz-sx4f-oss2-01 ~]#
[root@gz-sx4f-oss2-01 ~]# s3cmd -c test.cfg info s3://test3f
s3://test3f/ (bucket):
Location: testgroup
Payer: BucketOwner
Expiration Rule: none
Policy: none
CORS: none
ACL: test1: FULL_CONTROL
[root@gz-sx4f-oss2-01 ~]#

Hi @Tave - The bucket here is test3f right? but the resource in the policy is set to "Resource": "arn:aws:s3:::test1", I think test1 is the user in your s3cfg. The resource should be set to the ARN of the bucket, i.e., arn:aws:s3:::test3f

Actions #10

Updated by Amine Liu almost 6 years ago

sorry, My mistake. test ok on 12.2.5 now, but failed on 12.2.1

Actions #11

Updated by Pritha Srivastava almost 6 years ago

Tave liu wrote:

sorry, My mistake. test ok on 12.2.5 now, but failed on 12.2.1

So this issue can be closed right?

Actions #12

Updated by Amine Liu almost 6 years ago

Pritha Srivastava wrote:

Tave liu wrote:

sorry, My mistake. test ok on 12.2.5 now, but failed on 12.2.1

So this issue can be closed right?

YES

Actions

Also available in: Atom PDF