Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2735 from acmesh-official/dev
sync
- Loading branch information
Showing
9 changed files
with
1,000 additions
and
6 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#!/usr/bin/env sh | ||
|
||
# Script to deploy certificates to Palo Alto Networks PANOS via API | ||
# Note PANOS API KEY and IP address needs to be set prior to running. | ||
# The following variables exported from environment will be used. | ||
# If not set then values previously saved in domain.conf file are used. | ||
# | ||
# Firewall admin with superuser and IP address is required. | ||
# | ||
# export PANOS_USER="" # required | ||
# export PANOS_PASS="" # required | ||
# export PANOS_HOST="" # required | ||
|
||
# This function is to parse the XML | ||
parse_response() { | ||
type=$2 | ||
if [ "$type" = 'keygen' ]; then | ||
status=$(echo "$1" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g') | ||
if [ "$status" = "success" ]; then | ||
panos_key=$(echo "$1" | sed 's/^.*\(<key>\)\(.*\)<\/key>.*/\2/g') | ||
_panos_key=$panos_key | ||
else | ||
message="PAN-OS Key could not be set." | ||
fi | ||
else | ||
status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g') | ||
message=$(echo "$1" | sed 's/^.*<result>\(.*\)<\/result.*/\1/g') | ||
fi | ||
return 0 | ||
} | ||
|
||
deployer() { | ||
content="" | ||
type=$1 # Types are keygen, cert, key, commit | ||
_debug "**** Deploying $type *****" | ||
panos_url="https://$_panos_host/api/" | ||
if [ "$type" = 'keygen' ]; then | ||
_H1="Content-Type: application/x-www-form-urlencoded" | ||
content="type=keygen&user=$_panos_user&password=$_panos_pass" | ||
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}" | ||
fi | ||
|
||
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then | ||
#Generate DEIM | ||
delim="-----MultipartDelimiter$(date "+%s%N")" | ||
nl="\015\012" | ||
#Set Header | ||
export _H1="Content-Type: multipart/form-data; boundary=$delim" | ||
if [ "$type" = 'cert' ]; then | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\ncertificate" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" | ||
fi | ||
if [ "$type" = 'key' ]; then | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\nprivate-key" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n\r\n123456" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" | ||
fi | ||
#Close multipart | ||
content="$content${nl}--$delim--${nl}" | ||
#Convert CRLF | ||
content=$(printf %b "$content") | ||
fi | ||
|
||
if [ "$type" = 'commit' ]; then | ||
export _H1="Content-Type: application/x-www-form-urlencoded" | ||
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode) | ||
content="type=commit&key=$_panos_key&cmd=$cmd" | ||
fi | ||
response=$(_post "$content" "$panos_url" "" "POST") | ||
parse_response "$response" "$type" | ||
# Saving response to variables | ||
response_status=$status | ||
#DEBUG | ||
_debug response_status "$response_status" | ||
if [ "$response_status" = "success" ]; then | ||
_debug "Successfully deployed $type" | ||
return 0 | ||
else | ||
_err "Deploy of type $type failed. Try deploying with --debug to troubleshoot." | ||
_debug "$message" | ||
return 1 | ||
fi | ||
} | ||
|
||
# This is the main function that will call the other functions to deploy everything. | ||
panos_deploy() { | ||
_cdomain="$1" | ||
_ckey="$2" | ||
_cfullchain="$5" | ||
# PANOS ENV VAR check | ||
if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then | ||
_debug "No ENV variables found lets check for saved variables" | ||
_getdeployconf PANOS_USER | ||
_getdeployconf PANOS_PASS | ||
_getdeployconf PANOS_HOST | ||
_panos_user=$PANOS_USER | ||
_panos_pass=$PANOS_PASS | ||
_panos_host=$PANOS_HOST | ||
if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then | ||
_err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs." | ||
return 1 | ||
else | ||
_debug "Using saved env variables." | ||
fi | ||
else | ||
_debug "Detected ENV variables to be saved to the deploy conf." | ||
# Encrypt and save user | ||
_savedeployconf PANOS_USER "$PANOS_USER" 1 | ||
_savedeployconf PANOS_PASS "$PANOS_PASS" 1 | ||
_savedeployconf PANOS_HOST "$PANOS_HOST" 1 | ||
_panos_user="$PANOS_USER" | ||
_panos_pass="$PANOS_PASS" | ||
_panos_host="$PANOS_HOST" | ||
fi | ||
_debug "Let's use username and pass to generate token." | ||
if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then | ||
_err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST" | ||
return 1 | ||
else | ||
_debug "Getting PANOS KEY" | ||
deployer keygen | ||
if [ -z "$_panos_key" ]; then | ||
_err "Missing apikey." | ||
return 1 | ||
else | ||
deployer cert | ||
deployer key | ||
deployer commit | ||
fi | ||
fi | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#!/usr/bin/env sh | ||
|
||
# Here is a script to deploy cert to Synology DSM | ||
# | ||
# it requires the jq and curl are in the $PATH and the following | ||
# environment variables must be set: | ||
# | ||
# SYNO_Username - Synology Username to login (must be an administrator) | ||
# SYNO_Password - Synology Password to login | ||
# SYNO_Certificate - Certificate description to target for replacement | ||
# | ||
# The following environmental variables may be set if you don't like their | ||
# default values: | ||
# | ||
# SYNO_Scheme - defaults to http | ||
# SYNO_Hostname - defaults to localhost | ||
# SYNO_Port - defaults to 5000 | ||
# | ||
#returns 0 means success, otherwise error. | ||
|
||
######## Public functions ##################### | ||
|
||
_syno_get_cookie_data() { | ||
grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' | ||
} | ||
|
||
#domain keyfile certfile cafile fullchain | ||
synology_dsm_deploy() { | ||
|
||
_cdomain="$1" | ||
_ckey="$2" | ||
_ccert="$3" | ||
_cca="$4" | ||
|
||
_debug _cdomain "$_cdomain" | ||
|
||
# Get Username and Password, but don't save until we successfully authenticate | ||
_getdeployconf SYNO_Username | ||
_getdeployconf SYNO_Password | ||
_getdeployconf SYNO_Create | ||
if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then | ||
SYNO_Username="" | ||
SYNO_Password="" | ||
_err "SYNO_Username & SYNO_Password must be set" | ||
return 1 | ||
fi | ||
_debug2 SYNO_Username "$SYNO_Username" | ||
_secure_debug2 SYNO_Password "$SYNO_Password" | ||
|
||
# Optional scheme, hostname, and port for Synology DSM | ||
_getdeployconf SYNO_Scheme | ||
_getdeployconf SYNO_Hostname | ||
_getdeployconf SYNO_Port | ||
|
||
# default vaules for scheme, hostname, and port | ||
# defaulting to localhost and http because it's localhost... | ||
[ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http" | ||
[ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost" | ||
[ -n "${SYNO_Port}" ] || SYNO_Port="5000" | ||
|
||
_savedeployconf SYNO_Scheme "$SYNO_Scheme" | ||
_savedeployconf SYNO_Hostname "$SYNO_Hostname" | ||
_savedeployconf SYNO_Port "$SYNO_Port" | ||
|
||
_debug2 SYNO_Scheme "$SYNO_Scheme" | ||
_debug2 SYNO_Hostname "$SYNO_Hostname" | ||
_debug2 SYNO_Port "$SYNO_Port" | ||
|
||
# Get the certificate description, but don't save it until we verfiy it's real | ||
_getdeployconf SYNO_Certificate | ||
if [ -z "${SYNO_Certificate:?}" ]; then | ||
_err "SYNO_Certificate needs to be defined (with the Certificate description name)" | ||
return 1 | ||
fi | ||
_debug SYNO_Certificate "$SYNO_Certificate" | ||
|
||
_base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" | ||
_debug _base_url "$_base_url" | ||
|
||
# Login, get the token from JSON and session id from cookie | ||
_info "Logging into $SYNO_Hostname:$SYNO_Port" | ||
response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes") | ||
token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') | ||
_debug3 response "$response" | ||
|
||
if [ -z "$token" ]; then | ||
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." | ||
_err "Check your username and password." | ||
return 1 | ||
fi | ||
|
||
_H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" | ||
_H2="X-SYNO-TOKEN: $token" | ||
export _H1 | ||
export _H2 | ||
_debug2 H1 "${_H1}" | ||
_debug2 H2 "${_H2}" | ||
|
||
# Now that we know the username and password are good, save them | ||
_savedeployconf SYNO_Username "$SYNO_Username" | ||
_savedeployconf SYNO_Password "$SYNO_Password" | ||
_debug token "$token" | ||
|
||
_info "Getting certificates in Synology DSM" | ||
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") | ||
_debug3 response "$response" | ||
id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") | ||
_debug2 id "$id" | ||
|
||
if [ -z "$id" ] && [ -z "${SYNO_Create:?}" ]; then | ||
_err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" | ||
return 1 | ||
fi | ||
|
||
# we've verified this certificate description is a thing, so save it | ||
_savedeployconf SYNO_Certificate "$SYNO_Certificate" | ||
|
||
default=false | ||
if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then | ||
default=true | ||
fi | ||
_debug2 default "$default" | ||
|
||
_info "Generate form POST request" | ||
nl="\015\012" | ||
delim="--------------------------$(_utc_date | tr -d -- '-: ')" | ||
content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\012" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\012" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\012" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" | ||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}${default}" | ||
content="$content${nl}--$delim--${nl}" | ||
content="$(printf "%b_" "$content")" | ||
content="${content%_}" # protect trailing \n | ||
|
||
_info "Upload certificate to the Synology DSM" | ||
response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" "" "POST" "multipart/form-data; boundary=${delim}") | ||
_debug3 response "$response" | ||
|
||
if ! echo "$response" | grep '"error":' >/dev/null; then | ||
if echo "$response" | grep '"restart_httpd":true' >/dev/null; then | ||
_info "http services were restarted" | ||
else | ||
_info "http services were NOT restarted" | ||
fi | ||
return 0 | ||
else | ||
_err "Unable to update certificate, error code $response" | ||
return 1 | ||
fi | ||
} |
Oops, something went wrong.