Created
October 13, 2017 09:48
-
-
Save mhofman/f8e1fdd5dce49abacf5fd776fb3727ce to your computer and use it in GitHub Desktop.
Generate a signed certificate valid to connect locally to a Lutron Caseta Smart Bridge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Usage: get_lutron_cert.sh [bridge_ip] | tee cert.pem | |
function error() { | |
echo "Error: $1" >&2 | |
exit 1 | |
} | |
login_server="device-login.lutron.com" | |
app_client_id="e001a4471eb6152b7b3f35e549905fd8589dfcf57eb680b6fb37f20878c28e5a" | |
app_client_secret="b07fee362538d6df3b129dc3026a72d27e1005a3d1e5839eed5ed18c63a89b27" | |
app_oauth_redirect_page="lutron_app_oauth_redirect" | |
cert_subject="/C=US/ST=Pennsylvania/L=Coopersburg/O=Lutron Electronics Co., Inc./CN=Lutron Caseta App" | |
base_url="https://${login_server}/" | |
redirect_uri_param="https%3A%2F%2F${login_server}%2F${app_oauth_redirect_page}" | |
authorize_url="${base_url}oauth/authorize?client_id=${app_client_id}&redirect_uri=${redirect_uri_param}&response_type=code" | |
openssl version >/dev/null || error "openssl required" | |
jq --version >/dev/null || error "jq required" | |
echo "Open Browser and login at ${authorize_url}" >&2 | |
echo "Enter the URL (of the \"error\" page you got redirected to (or the code in the URL): " >&2 | |
read -r redirected_url | |
oauth_code=`echo ${redirected_url} | sed -e's/^\(.*\?code=\)\{0,1\}\([0-9a-f]*\)\s*$/\2/;t;d'` | |
[ -n "$oauth_code" ] || error "Invalid code" | |
private_key="`openssl genrsa 2048 2>/dev/null`" | |
escaped_csr="`echo \"$private_key\" | openssl req -new -key /proc/self/fd/0 -subj \"${cert_subject}\" | awk 'NF {sub(/\r/, \"\"); printf \"%s\\\\n\",$0;}'`" | |
[ -n "$escaped_csr" ] || error "Couldn't generate CSR" | |
token="`curl -s -X POST -d \"code=${oauth_code}&client_id=${app_client_id}&client_secret=${app_client_secret}&redirect_uri=${redirect_uri_param}&grant_type=authorization_code\" ${base_url}oauth/token`" | |
[ "bearer" == "`echo \"$token\" | jq -r '.token_type'`" ] || error "Received invalid token $token. Try generating a new code (one time use)." | |
access_token="`echo \"$token\" | jq -r '.access_token'`" | |
pairing_request_content="{\"remote_signs_app_certificate_signing_request\":\"${escaped_csr}\"}" | |
pairing_response="`echo \"$pairing_request_content\" | curl -s -X POST -H \"X-DeviceType: Caseta,RA2Select\" -H \"Content-Type: application/json\" -H \"Authorization: Bearer ${access_token}\" -d \"@-\" ${base_url}api/v1/remotepairing/application/user`" | |
#echo "$pairing_response" | |
app_cert="`echo \"$pairing_response\" | jq -r '.remote_signs_app_certificate'`" | |
remote_cert="`echo \"$pairing_response\" | jq -r '.local_signs_remote_certificate'`" | |
echo "$app_cert" | openssl x509 -noout || error "Received invalid app cert in pairing response $pairing_response" | |
echo "$remote_cert" | openssl x509 -noout || error "Received invalid remote cert in pairing response $pairing_response" | |
echo -e "$private_key\n$app_cert\n$remote_cert" | |
server_addr=$1 | |
[ -n "$server_addr" ] || exit 0 | |
echo "$app_cert" | { echo "$private_key" | { echo "$remote_cert" | { | |
leap_response=`(echo '{"CommuniqueType":"ReadRequest","Header":{"Url":"/server/1/status/ping"}}'; sleep 3) 3<&- 4<&- 5<&- | openssl s_client -connect "$server_addr:8081" -cert /proc/self/fd/3 -key /proc/self/fd/4 -CAfile /proc/self/fd/5 -quiet -no_ign_eof 2>/dev/null` | |
[ "$?" -eq "0" ] || error "Could not connect to bridge" | |
echo "Successfully connected to bridge, running LEAP Server version `echo \"$leap_response\" | jq -r '.Body.PingResponse.LEAPVersion'`" >&2 | |
} 5<&0; } 4<&0; } 3<&0 |
I'll second i was getting invalid code, but @nriley's mods worked
@nriley Were you able to ever determine with you were getting an empty pairing_response?
FYI, it looks like the error page (line 24-27) no longer works -- Lutron redirects you to their login page now. Stinks because it looks like Lutron refreshed their certs so the ones I pulled in November no longer work!
Confirmed, also getting invalid config with the certs generated.
I also cannot get the certificate.
I modified the script to just run curl in verbose mode, and that's what I'm getting (replaced long keys with (...) ):
Open Browser and login at https://device-login.lutron.com/oauth/authorize?client_id=e0(...)5a&redirect_uri=https%3A%2F%2Fdevice-login.lutron.com%2Flutron_app_oauth_redirect&response_type=code
Enter the URL (of the "error" page you got redirected to (or the code in the URL):
67(...)8a4
Request: '{"remote_signs_app_certificate_signing_request":"-----BEGIN CERTIFICATE REQUEST-----\nMIICwjCCAaoCAQAwfTELMAkGA1UEBhMCVVMxFTATBgNVBAgMDFBlbm5zeWx2YW5p\n(...)\nXgTCob8JM8NCuzKWkeIFpnLWXVoIIv2qEk2MVrFUg8dX8+B/cMU=\n-----END CERTIFICATE REQUEST-----\n"}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 54.243.113.58...
* TCP_NODELAY set
* Connected to device-login.lutron.com (54.243.113.58) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=US; ST=Pennsylvania; L=Coopersburg; O=Lutron Electronics Co., Inc.; OU=IT; CN=device-login.lutron.com
* start date: Feb 13 00:00:00 2018 GMT
* expire date: Feb 12 12:00:00 2021 GMT
* subjectAltName: host "device-login.lutron.com" matched cert's "device-login.lutron.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=Thawte RSA CA 2018
* SSL certificate verify ok.
> POST /api/v1/remotepairing/application/user HTTP/1.1
> Host: device-login.lutron.com
> User-Agent: curl/7.59.0
> Accept: */*
> X-DeviceType: Caseta,RA2Select
> Content-Type: application/json
> Authorization: Bearer 3859(...)df6c
> Content-Length: 1103
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 400 Bad Request
< Server: Cowboy
< Date: Wed, 09 May 2018 01:14:12 GMT
< Connection: keep-alive
< Content-Type: text/html; charset=utf-8
< X-Request-Id: ec2fb587-d1ab-4aa9-ac13-4b82c5d10e33
< X-Runtime: 0.004386
< Content-Length: 0
< Via: 1.1 vegur
<
* Connection #0 to host device-login.lutron.com left intact
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried this and pasted in my code, but it gave me an error:
My code is (couple of # in middle for privacy if it matters, I'm not sure)
4cfea4fdca36a489fc7095ab99b96bd7079671#####27a0dd96e384a9df8f6d
Edit: Nriley's code worked.