# frozen_string_literal: truemoduleAwsmoduleS3modulePlugins# @api privateclassAccessGrants<Seahorse::Client::Plugin@s3control=beginrequire'aws-sdk-s3control'truerescueLoadErrorfalseendoption(:access_grants,default: false,doc_type: 'Boolean',docstring: <<-DOCS)
When `true`, the S3 client will use the S3 Access Grants feature to
authenticate requests. Bucket credentials will be fetched from S3
Control using the `get_data_access` API.
DOCSoption(:access_grants_credentials_provider,doc_type: 'Aws::S3::AccessGrantsCredentialsProvider',rbs_type: 'untyped',docstring: <<-DOCS)do|_cfg|
When `access_grants` is `true`, this option can be used to provide
additional options to the credentials provider, including a privilege
setting, caching, and fallback behavior.
DOCSAws::S3::AccessGrantsCredentialsProvider.newend# @api privateclassHandler<Seahorse::Client::HandlerPERMISSION_MAP={head_object: 'READ',get_object: 'READ',get_object_acl: 'READ',list_multipart_uploads: 'READ',list_objects_v2: 'READ',list_object_versions: 'READ',list_parts: 'READ',head_bucket: 'READ',get_object_attributes: 'READ',put_object: 'WRITE',put_object_acl: 'WRITE',delete_object: 'WRITE',abort_multipart_upload: 'WRITE',create_multipart_upload: 'WRITE',upload_part: 'WRITE',complete_multipart_upload: 'WRITE',delete_objects: 'WRITE',copy_object: 'READWRITE'}.freezedefcall(context)provider=context.config.access_grants_credentials_providerifaccess_grants_operation?(context)&&!s3_express_endpoint?(context)&&!credentials_head_bucket_call?(provider)params=context[:endpoint_params]permission=PERMISSION_MAP[context.operation_name]key=casecontext.operation_namewhen:delete_objectsdelete_params=context.params[:delete]common_prefixes(delete_params[:objects].map{|o|o[:key]})when:copy_objectsource_bucket,source_key=params[:copy_source].split('/',2)ifparams[:bucket]!=source_bucketraiseArgumentError,'source and destination bucket must be the same'endcommon_prefixes([params[:key],source_key])elseparams[:key]endcredentials=provider.access_grants_credentials_for(bucket: params[:bucket],key: key,prefix: params[:prefix],permission: permission)context[:sigv4_credentials]=credentials# Sign will use thisendwith_metric(credentials){@handler.call(context)}endprivatedefwith_metric(credentials,&block)returnblock.callunlesscredentialsAws::Plugins::UserAgent.metric('S3_ACCESS_GRANTS',&block)end# HeadBucket is a supported call. When fetching credentials,# this plugin is executed again, and becomes recursive.defcredentials_head_bucket_call?(provider)provider.instance_variable_get(:@head_bucket_call)enddefaccess_grants_operation?(context)params=context[:endpoint_params]params[:bucket]&&PERMISSION_MAP[context.operation_name]enddefs3_express_endpoint?(context)context[:endpoint_properties]['backend']=='S3Express'end# Return the common prefix of the keys, regardless of the delimiter.# For example, given keys ['foo/bar', 'foo/baz'], the common prefix# is 'foo/ba'.defcommon_prefixes(keys)return''ifkeys.empty?first_key=keys[0]common_ancestor=first_keylast_prefix=''keys.eachdo|k|untilcommon_ancestor.empty?breakifk.start_with?(common_ancestor)last_index=common_ancestor.rindex('/')return''iflast_index.nil?last_prefix=common_ancestor[(last_index+1)..-1]common_ancestor=common_ancestor[0...last_index]endendnew_common_ancestor="#{common_ancestor}/#{last_prefix}"keys.eachdo|k|untillast_prefix.empty?breakifk.start_with?(new_common_ancestor)last_prefix=last_prefix[0...-1]new_common_ancestor="#{common_ancestor}/#{last_prefix}"endendifnew_common_ancestor=="#{first_key}/"first_keyelsenew_common_ancestorendendenddefadd_handlers(handlers,config)returnunlessAccessGrants.s3control?&&config.access_grantshandlers.add(Handler)enddefafter_initialize(client)returnunlessAccessGrants.s3control?&&client.config.access_grantsprovider=client.config.access_grants_credentials_providerprovider.s3_client=clientunlessprovider.s3_clientendclass<<selfdefs3control?@s3controlendendendendendend