Skip to content

Instantly share code, notes, and snippets.

@mhofman
Created October 13, 2017 09:48
Show Gist options
  • Save mhofman/f8e1fdd5dce49abacf5fd776fb3727ce to your computer and use it in GitHub Desktop.
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
#!/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
@sberryman
Copy link

Confirmed, also getting invalid config with the certs generated.

@sjakub
Copy link

sjakub commented May 9, 2018

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