forked from TrueCloudLab/frostfs-s3-gw
[TrueCloudLab#32] Add custom policy unmarshaler
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
32bf915502
commit
64e7356acc
2 changed files with 163 additions and 0 deletions
|
@ -158,6 +158,90 @@ func (s ServiceRecord) ToEACLRecord() *eacl.Record {
|
||||||
return serviceRecord
|
return serviceRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidStatement = stderrors.New("invalid statement")
|
||||||
|
errInvalidPrincipal = stderrors.New("invalid principal")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *statement) UnmarshalJSON(data []byte) error {
|
||||||
|
var statementMap map[string]interface{}
|
||||||
|
if err := json.Unmarshal(data, &statementMap); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sidField, ok := statementMap["Sid"]
|
||||||
|
if ok {
|
||||||
|
if s.Sid, ok = sidField.(string); !ok {
|
||||||
|
return errInvalidStatement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
effectField, ok := statementMap["Effect"]
|
||||||
|
if ok {
|
||||||
|
if s.Effect, ok = effectField.(string); !ok {
|
||||||
|
return errInvalidStatement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
principalField, ok := statementMap["Principal"]
|
||||||
|
if ok {
|
||||||
|
principalMap, ok := principalField.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return errInvalidPrincipal
|
||||||
|
}
|
||||||
|
|
||||||
|
awsField, ok := principalMap["AWS"]
|
||||||
|
if ok {
|
||||||
|
if s.Principal.AWS, ok = awsField.(string); !ok {
|
||||||
|
return fmt.Errorf("%w: 'AWS' field must be string", errInvalidPrincipal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canonicalUserField, ok := principalMap["CanonicalUser"]
|
||||||
|
if ok {
|
||||||
|
if s.Principal.CanonicalUser, ok = canonicalUserField.(string); !ok {
|
||||||
|
return errInvalidPrincipal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actionField, ok := statementMap["Action"]
|
||||||
|
if ok {
|
||||||
|
switch actionField := actionField.(type) {
|
||||||
|
case []interface{}:
|
||||||
|
s.Action = make([]string, len(actionField))
|
||||||
|
for i, action := range actionField {
|
||||||
|
if s.Action[i], ok = action.(string); !ok {
|
||||||
|
return errInvalidStatement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
s.Action = []string{actionField}
|
||||||
|
default:
|
||||||
|
return errInvalidStatement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceField, ok := statementMap["Resource"]
|
||||||
|
if ok {
|
||||||
|
switch resourceField := resourceField.(type) {
|
||||||
|
case []interface{}:
|
||||||
|
s.Resource = make([]string, len(resourceField))
|
||||||
|
for i, action := range resourceField {
|
||||||
|
if s.Resource[i], ok = action.(string); !ok {
|
||||||
|
return errInvalidStatement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
s.Resource = []string{resourceField}
|
||||||
|
default:
|
||||||
|
return errInvalidStatement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := api.GetReqInfo(r.Context())
|
||||||
|
|
||||||
|
|
|
@ -1352,6 +1352,85 @@ func TestBucketPolicy(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBucketPolicyUnmarshal(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
policy string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "action/resource array",
|
||||||
|
policy: `
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [{
|
||||||
|
"Principal": {
|
||||||
|
"AWS": "arn:aws:iam::111122223333:role/JohnDoe"
|
||||||
|
},
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"s3:GetObject",
|
||||||
|
"s3:GetObjectVersion"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
|
||||||
|
"arn:aws:s3:::DOC-EXAMPLE-BUCKET2/*"
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "action/resource string",
|
||||||
|
policy: `
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [{
|
||||||
|
"Principal": {
|
||||||
|
"AWS": "arn:aws:iam::111122223333:role/JohnDoe"
|
||||||
|
},
|
||||||
|
"Effect": "Deny",
|
||||||
|
"Action": "s3:GetObject",
|
||||||
|
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
bktPolicy := &bucketPolicy{}
|
||||||
|
err := json.Unmarshal([]byte(tc.policy), bktPolicy)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPutBucketPolicy(t *testing.T) {
|
||||||
|
bktPolicy := `
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [{
|
||||||
|
"Principal": {
|
||||||
|
"AWS": "*"
|
||||||
|
},
|
||||||
|
"Effect": "Deny",
|
||||||
|
"Action": "s3:GetObject",
|
||||||
|
"Resource": "arn:aws:s3:::bucket-for-policy/*"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
hc := prepareHandlerContext(t)
|
||||||
|
bktName := "bucket-for-policy"
|
||||||
|
|
||||||
|
box, _ := createAccessBox(t)
|
||||||
|
createBucket(t, hc, bktName, box)
|
||||||
|
|
||||||
|
w, r := prepareTestPayloadRequest(hc, bktName, "", bytes.NewReader([]byte(bktPolicy)))
|
||||||
|
ctx := context.WithValue(r.Context(), api.BoxData, box)
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
hc.Handler().PutBucketPolicyHandler(w, r)
|
||||||
|
assertStatus(hc.t, w, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
func getBucketPolicy(hc *handlerContext, bktName string) *bucketPolicy {
|
func getBucketPolicy(hc *handlerContext, bktName string) *bucketPolicy {
|
||||||
w, r := prepareTestRequest(hc, bktName, "", nil)
|
w, r := prepareTestRequest(hc, bktName, "", nil)
|
||||||
hc.Handler().GetBucketPolicyHandler(w, r)
|
hc.Handler().GetBucketPolicyHandler(w, r)
|
||||||
|
|
Loading…
Reference in a new issue