Create an empty target group. Call it whatever you like, e.g.
blackhole. Select the correct VPC if you have more than one. The rest of the parameters for the new target group can be left at their default values. Don't assign any instances to the target group.
Create a rule for each listener on your ALB,
IF path is /admin*
THEN Forward to blackhole. Put this as high on the list as it needs to be.
Since 100% of the 0 targets in the target group will always be unhealthy, the ALB will always fail to deliver the request to a back-end, and thus will throw an error when any request matching this path arrives. The wildcard
* matches 0 or more characters, so everything under this path is effectively denied by this rule.
$ curl -v xxxx.us-west-2.elb.amazonaws.com/admin
* About to connect() to xxxx.us-west-2.elb.amazonaws.com port 80 (#0)
* Trying x.x.x.x... connected
> GET /admin HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/126.96.36.199 libidn/1.23 librtmp/2.3
> Host: xxxx.us-west-2.elb.amazonaws.com
> Accept: */*
< HTTP/1.1 503 Service Temporarily Unavailable
< Server: awselb/2.0
< Date: Thu, 10 Aug 2017 16:38:15 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
<head><title>503 Service Temporarily Unavailable</title></head>
<center><h1>503 Service Temporarily Unavailable</h1></center>
* Connection #0 to host xxxx.us-west-2.elb.amazonaws.com left intact
* Closing connection #0
Granted, the error is not entirely truthful, since it's
503 Service Temporarily Unavailable rather than
403 Forbidden, but this does accomplish the purpose of blocking specific path patterns on ALB.