@@ -88,17 +88,18 @@ function generate_jwt()
88
88
{
89
89
# Get a JSON Web Token to authenicate against the HMPPS Bot.
90
90
# The HMPPS bot can provide exchange this for a GitHub Token for action GitHub workflows.
91
-
92
91
BOT_APP_ID=$( aws ssm get-parameter --name " /github/hmpps_bot_app_id" --query " Parameter.Value" --with-decryption --output text)
93
92
BOT_PRIVATE_KEY=$( aws ssm get-parameter --name " /github/hmpps_bot_priv_key" --query " Parameter.Value" --with-decryption --output text)
94
93
95
- # Define expiry time for JWT
94
+ # Define expiry time for JWT - we will be using it immediately so just use a 10 minute expiry time.
96
95
NOW=$( date +%s)
97
- INITIAL=$(( ${NOW} - 60 )) # Issues 60 seconds in the past
96
+ INITIAL=$(( ${NOW} - 60 )) # Issues 60 seconds in the past (avoid time jitter problem)
98
97
EXPIRY=$(( ${NOW} + 600 )) # Expires 10 minutes in the future
99
98
99
+ # This function is used to apply Base64 encoding for the token to allow it to be passed on.
100
100
b64enc () { openssl base64 | tr -d ' =' | tr ' /+' ' _-' | tr -d ' \n' ; }
101
101
102
+ # The JWT requires a Header, Payload and Signature as defined here.
102
103
HEADER_JSON=' {
103
104
"typ":"JWT",
104
105
"alg":"RS256"
@@ -111,7 +112,7 @@ PAYLOAD_JSON='{
111
112
"exp":' " ${EXPIRY} " ' ,
112
113
"iss":' " ${BOT_APP_ID} " '
113
114
}'
114
- # Payload encode
115
+ # Payload encode in Base64
115
116
PAYLOAD=$( echo -n " ${PAYLOAD_JSON} " | b64enc )
116
117
117
118
# Signature
@@ -138,23 +139,33 @@ printf '%s\n' "$GITHUB_TOKEN"
138
139
139
140
function github_repository_dispatch()
140
141
{
142
+ # Because this script is intended to run asynchronously and may be called by a GitHub Workflow, we use
143
+ # GitHub Repository Dispatch events to call back to the Workflow to allow it to continue. This is a
144
+ # workaround to avoid two issues:
145
+ # (1) Timeout of GitHub actions lasting over 6 hours.
146
+ # (2) Billing costs associated with the GitHub hosted runner actively waiting whilst the backup runs.
147
+ #
148
+ # We supply 2 parameters to this function:
149
+ # EVENT_TYPE is a user-defined event to pass to the GitHub repository. The backup worflow is triggered
150
+ # for either oracle-db-backup-sucess or oracle-db-backup-failure events. These are the only 2 which
151
+ # should be used.
152
+ # JSON_PAYLOAD is the JSON originally passed to the script using the -j switch. This allows the
153
+ # workflow to continue where it left off because this JSON contains the name of the environment, host
154
+ # and period of the backup, along with any associated parameters.
141
155
EVENT_TYPE=$1
142
156
JSON_PAYLOAD=$2
143
157
GITHUB_TOKEN_VALUE=$( get_github_token | jq -r ' .token' )
158
+ # We set the Phase in the JSON payload corresponding to whether the backup has succeeded or failed.
159
+ # This is informational only - it is GitHub event type (oracle-db-backup-success/failure) which
160
+ # determines what the workflow does next.
144
161
if [[ " $EVENT_TYPE " == " oracle-db-backup-success" ]]; then
145
162
JSON_PAYLOAD=$( echo $JSON_PAYLOAD | jq -r ' .Phase = "Backup Succeeded"' )
146
163
else
147
164
JSON_PAYLOAD=$( echo $JSON_PAYLOAD | jq -r ' .Phase = "Backup Failed"' )
148
165
fi
149
- info " Running Repository Dispatch:${EVENT_TYPE} :${JSON_PAYLOAD} :${GITHUB_TOKEN_VALUE} "
150
166
JSON_DATA=" {\" event_type\" : \" ${EVENT_TYPE} \" ,\" client_payload\" :${JSON_PAYLOAD} }"
151
- info " JD1: $JSON_DATA "
152
- JSON_DATA=$( echo $JSON_DATA | jq @json)
153
- info " JD2: $JSON_DATA "
154
- cat << EOCURL | tee -a /tmp/eocurl.txt
155
- curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token ${GITHUB_TOKEN_VALUE} " --data ${JSON_DATA} ${REPOSITORY_DISPATCH}
156
- EOCURL
157
- curl -X POST -H " Accept: application/vnd.github+json" -H " Authorization: token ${GITHUB_TOKEN_VALUE} " --data ${JSON_DATA} ${REPOSITORY_DISPATCH}
167
+ info " Posting repository dispatch event"
168
+ curl -X POST -H " Accept: application/vnd.github+json" -H " Authorization: token ${GITHUB_TOKEN_VALUE} " --data-raw " ${JSON_DATA} " ${REPOSITORY_DISPATCH}
158
169
RC=$?
159
170
if [[ $RC -ne 0 ]]; then
160
171
# We cannot use the error function for dispatch failures as it contains its own dispatch call
@@ -184,17 +195,14 @@ update_ssm_parameter () {
184
195
MESSAGE=$2
185
196
info " Updating SSM Parameter ${SSM_PARAMETER} Message to ${MESSAGE} "
186
197
SSM_VALUE=$( aws ssm get-parameter --name " ${SSM_PARAMETER} " --query " Parameter.Value" --output text)
187
- info " I: $NEW_SSM_VALUE "
188
198
NEW_SSM_VALUE=$( echo ${SSM_VALUE} | jq -r --arg MESSAGE " $MESSAGE " ' .Message=$MESSAGE' )
189
- info " B: $NEW_SSM_VALUE "
190
199
if [[ " $STATUS " == " Success" ]]; then
191
200
NEW_SSM_VALUE=$( echo ${NEW_SSM_VALUE} | jq -r ' .Phase = "Backup Succeeded"' )
192
201
elif [[ " $STATUS " == " Running" ]]; then
193
202
NEW_SSM_VALUE=$( echo ${NEW_SSM_VALUE} | jq -r ' .Phase = "Backup In Progress"' )
194
203
else
195
204
NEW_SSM_VALUE=$( echo ${NEW_SSM_VALUE} | jq -r ' .Phase = "Backup Failed"' )
196
205
fi
197
- info " A: $NEW_SSM_VALUE "
198
206
aws ssm put-parameter --name " ${SSM_PARAMETER} " --type String --overwrite --value " ${NEW_SSM_VALUE} " 1>&2
199
207
}
200
208
@@ -739,6 +747,21 @@ info "Trace File = $TRACE_FILE"
739
747
info " Archivelog Range = $ARCHIVELOGS "
740
748
info " Specific Datafiles = $DATAFILES "
741
749
750
+ if [[ ! -z " $REPOSITORY_DISPATCH " ]]; then
751
+ REPOSITORY_DISPATCH=" https://api.github.com/repos/${REPOSITORY_DISPATCH} /dispatches"
752
+ info " GitHub Actions Repository Dispatch Events will be sent to : $REPOSITORY_DISPATCH "
753
+ fi
754
+
755
+ if [[ ! -z " $JSON_INPUTS " ]]; then
756
+ # The JSON Inputs are used to record the parameters originally passed to GitHub
757
+ # actions to start the backup job. These are only used for actioning a repository
758
+ # dispatch event to indicate the end of the backup job run. They do NOT
759
+ # override the command line options passed to the script.
760
+ JSON_INPUTS=$( echo $JSON_INPUTS | base64 --decode )
761
+ elif [[ ! -z " $REPOSITORY_DISPATCH " ]]; then
762
+ error " JSON inputs must be supplied using the -j option if Repository Dispatch Events are requested."
763
+ fi
764
+
742
765
validate user
743
766
info " Execute $THISUSER bash profile"
744
767
. $HOME /.bash_profile
@@ -784,23 +807,6 @@ if [[ ! -z "$SSM_PARAMETER" ]]; then
784
807
update_ssm_parameter " Running" " Running: $0 $* "
785
808
fi
786
809
787
- if [[ ! -z " $REPOSITORY_DISPATCH " ]]; then
788
- REPOSITORY_DISPATCH=" https://api.github.com/repos/${REPOSITORY_DISPATCH} /dispatches"
789
- info " GitHub Actions Repository Dispatch Events will be sent to : $REPOSITORY_DISPATCH "
790
- fi
791
-
792
- if [[ ! -z " $JSON_INPUTS " ]]; then
793
- # The JSON Inputs are used to record the parameters originally passed to GitHub
794
- # actions to start the backup job. These are only used for actioning a repository
795
- # dispatch event to indicate the end of the backup job run. They do NOT
796
- # override the command line options passed to the script.
797
- JSON_INPUTS=$( echo $JSON_INPUTS | base64 --decode )
798
- info " Original JSON Inputs to GitHub Action: $JSON_INPUTS "
799
- elif [[ ! -z " $REPOSITORY_DISPATCH " ]]; then
800
- error " JSON inputs must be supplied using the -j option if Repository Dispatch Events are requested."
801
- fi
802
-
803
- touch $RMANCMDFILE
804
810
info " Create rman tags and format"
805
811
create_tag_format
806
812
info " Generating rman command file"
0 commit comments