@@ -5,8 +5,10 @@ usage() {
55 cat << 'USAGE '
66Usage: scripts/smoke-s3-curl.sh
77
8- Run a credentialed S3 smoke test against the LibreFS HFS endpoint using only
9- curl's built-in AWS SigV4 support. The script creates a temporary bucket,
8+ Run a credentialed S3 smoke test against the LibreFS HFS endpoint. Public
9+ targets use curl's header SigV4 support; a private HF target uses a short-lived
10+ query signature so the normal Bearer header remains available to the HF gateway.
11+ The script creates a temporary bucket,
1012uploads one object, verifies signed and anonymous reads, applies a public-read
1113policy, then removes the temporary resources.
1214
@@ -20,6 +22,7 @@ Optional environment:
2022 S3_SMOKE_BUCKET Default: generated temporary bucket name
2123 S3_SMOKE_OBJECT Default: smoke.txt
2224 S3_SMOKE_PAYLOAD Default: generated timestamp payload
25+ HF_GATEWAY_TOKEN Enables private-Space query signing and HF Bearer auth
2326USAGE
2427}
2528
@@ -36,6 +39,8 @@ SECRET_KEY="${MINIO_ROOT_PASSWORD:-${AWS_SECRET_ACCESS_KEY:-}}"
3639BUCKET=" ${S3_SMOKE_BUCKET:- librefs-hfs-smoke-$(date -u +% Y% m% d% H% M% S)-$$ } "
3740OBJECT=" ${S3_SMOKE_OBJECT:- smoke.txt} "
3841PAYLOAD=" ${S3_SMOKE_PAYLOAD:- librefs-hfs smoke $(date -u +% Y-% m-% dT% H:% M:% SZ)} "
42+ ROOT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) /.." && pwd) "
43+ PRESIGNER=" $ROOT_DIR /scripts/presign-s3-request.py"
3944
4045case " $ENDPOINT " in
4146 http://* |https://* ) ;;
7277
7378hf_gateway_args=()
7479if [[ -n " ${HF_GATEWAY_TOKEN:- } " ]]; then
75- hf_gateway_args=(-H " X-HF- Authorization: Bearer ${HF_GATEWAY_TOKEN} " )
80+ hf_gateway_args=(-H " Authorization: Bearer ${HF_GATEWAY_TOKEN} " )
7681fi
7782
7883tmp_dir=" $( mktemp -d) "
@@ -86,33 +91,59 @@ bucket_created=0
8691object_uploaded=0
8792policy_applied=0
8893
94+ presigned_url () {
95+ local method=" $1 "
96+ local url=" $2 "
97+ AWS_ACCESS_KEY_ID=" $ACCESS_KEY " AWS_SECRET_ACCESS_KEY=" $SECRET_KEY " \
98+ python3 " $PRESIGNER " --method " $method " --url " $url " --region " $REGION "
99+ }
100+
89101signed_curl () {
90- curl --silent --show-error --fail-with-body \
91- " ${hf_gateway_args[@]} " \
92- --aws-sigv4 " aws:amz:${REGION} :s3" \
93- --user " ${ACCESS_KEY} :${SECRET_KEY} " \
94- " $@ "
102+ local method=" $1 "
103+ local url=" $2 "
104+ shift 2
105+ if [[ -n " ${HF_GATEWAY_TOKEN:- } " ]]; then
106+ url=" $( presigned_url " $method " " $url " ) "
107+ curl --silent --show-error --fail-with-body \
108+ " ${hf_gateway_args[@]} " -X " $method " " $@ " " $url "
109+ else
110+ curl --silent --show-error --fail-with-body \
111+ --aws-sigv4 " aws:amz:${REGION} :s3" \
112+ --user " ${ACCESS_KEY} :${SECRET_KEY} " \
113+ -X " $method " " $@ " " $url "
114+ fi
95115}
96116
97117signed_status () {
98- curl --silent --show-error \
99- " ${hf_gateway_args[@]} " \
100- --aws-sigv4 " aws:amz:${REGION} :s3" \
101- --user " ${ACCESS_KEY} :${SECRET_KEY} " \
102- -o " $status_body " \
103- -w ' %{http_code}' \
104- " $@ " || true
118+ local method=" $1 "
119+ local url=" $2 "
120+ local request_args=()
121+ if [[ " $method " == HEAD ]]; then
122+ request_args=(--head)
123+ else
124+ request_args=(-X " $method " )
125+ fi
126+ if [[ -n " ${HF_GATEWAY_TOKEN:- } " ]]; then
127+ url=" $( presigned_url " $method " " $url " ) "
128+ curl --silent --show-error " ${hf_gateway_args[@]} " \
129+ " ${request_args[@]} " -o " $status_body " -w ' %{http_code}' " $url " || true
130+ else
131+ curl --silent --show-error \
132+ --aws-sigv4 " aws:amz:${REGION} :s3" \
133+ --user " ${ACCESS_KEY} :${SECRET_KEY} " \
134+ " ${request_args[@]} " -o " $status_body " -w ' %{http_code}' " $url " || true
135+ fi
105136}
106137
107138cleanup () {
108139 if [[ " $policy_applied " -eq 1 ]]; then
109- signed_curl -X DELETE " $ENDPOINT /$BUCKET ?policy" > /dev/null 2>&1 || true
140+ signed_curl DELETE " $ENDPOINT /$BUCKET ?policy" > /dev/null 2>&1 || true
110141 fi
111142 if [[ " $object_uploaded " -eq 1 ]]; then
112- signed_curl -X DELETE " $ENDPOINT /$BUCKET /$OBJECT " > /dev/null 2>&1 || true
143+ signed_curl DELETE " $ENDPOINT /$BUCKET /$OBJECT " > /dev/null 2>&1 || true
113144 fi
114145 if [[ " $bucket_created " -eq 1 ]]; then
115- signed_curl -X DELETE " $ENDPOINT /$BUCKET " > /dev/null 2>&1 || true
146+ signed_curl DELETE " $ENDPOINT /$BUCKET " > /dev/null 2>&1 || true
116147 fi
117148 rm -rf " $tmp_dir "
118149}
@@ -138,25 +169,25 @@ EOF_POLICY
138169trap cleanup EXIT
139170
140171echo " ==> list buckets"
141- signed_curl " $ENDPOINT /" > /dev/null
172+ signed_curl GET " $ENDPOINT /" > /dev/null
142173
143174echo " ==> ensure temporary bucket does not already exist: $BUCKET "
144- bucket_status=" $( signed_status -I " $ENDPOINT /$BUCKET " ) "
175+ bucket_status=" $( signed_status HEAD " $ENDPOINT /$BUCKET " ) "
145176if [[ " $bucket_status " != " 404" ]]; then
146177 echo " Refusing to use bucket $BUCKET because HEAD returned HTTP $bucket_status , expected 404." >&2
147178 exit 1
148179fi
149180
150181echo " ==> create temporary bucket: $BUCKET "
151- signed_curl -X PUT " $ENDPOINT /$BUCKET " > /dev/null
182+ signed_curl PUT " $ENDPOINT /$BUCKET " > /dev/null
152183bucket_created=1
153184
154185echo " ==> upload object: $OBJECT "
155- signed_curl -X PUT --data-binary @" $payload_file " " $ENDPOINT / $BUCKET / $OBJECT " > /dev/null
186+ signed_curl PUT " $ENDPOINT / $BUCKET / $OBJECT " --data-binary @" $payload_file " > /dev/null
156187object_uploaded=1
157188
158189echo " ==> signed object download"
159- signed_curl " $ENDPOINT /$BUCKET /$OBJECT " -o " $signed_download "
190+ signed_curl GET " $ENDPOINT /$BUCKET /$OBJECT " -o " $signed_download "
160191if ! cmp -s " $payload_file " " $signed_download " ; then
161192 echo " Signed download content does not match uploaded payload." >&2
162193 exit 1
@@ -170,7 +201,7 @@ if [[ "$private_status" != "403" ]]; then
170201fi
171202
172203echo " ==> apply public-read bucket policy"
173- signed_curl -X PUT -H ' Content-Type: application/json' --data-binary @" $policy_file " " $ENDPOINT / $BUCKET ?policy " > /dev/null
204+ signed_curl PUT " $ENDPOINT / $BUCKET ?policy " -H ' Content-Type: application/json' --data-binary @" $policy_file " > /dev/null
174205policy_applied=1
175206
176207echo " ==> anonymous read succeeds after policy"
0 commit comments