Skip to content

Commit

Permalink
Add support for service accounts | Resolve labbots#122
Browse files Browse the repository at this point in the history
* Add guide in readme on how to generate

* Add -sa/--service-account flag

* access tokens created by sa will be saved in config, when the sa is given, then it will try to reuse the access token if valid
  • Loading branch information
Akianonymus committed Nov 4, 2020
1 parent acda590 commit 1b6bd25
Show file tree
Hide file tree
Showing 12 changed files with 804 additions and 374 deletions.
70 changes: 63 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
> It utilizes google drive api v3 and google OAuth2.0 to generate access tokens and to authorize application for uploading files/folders to your google drive.
- Minimal
- Two modes of authentication
- Oauth credentials
- Service account credentials
- Upload or Update files/folders
- Recursive folder uploading
- Sync your folders
Expand Down Expand Up @@ -50,6 +53,7 @@
- [Updation](#updation)
- [Usage](#usage)
- [Generating Oauth Credentials](#generating-oauth-credentials)
- [Generating service account credentials](#generating-service-account-credentials)
- [Enable Drive API](#enable-drive-api)
- [First Run](#first-run)
- [Config file](#config)
Expand Down Expand Up @@ -116,6 +120,9 @@ This repo contains two types of scripts, posix compatible and bash compatible.
| mktemp | To generate temporary files ( optional ) |
| sleep | Self explanatory |
| ps | To manage different processes |
| openssl | For service account usage ( optional ) |

Note: If openssl if not installed, then `-sa | --service-account` flag won't work, but script will install successfully.

<strong>If BASH is not available or BASH is available but version is less tham 4.x, then below programs are also required:</strong>

Expand Down Expand Up @@ -296,10 +303,14 @@ There are two methods:

## Usage

First, we need to obtain our oauth credentials, here's how to do it:
First, we have to authenticate.

There are two ways to authenticate, oauth credentials or service accounts. Use any one.

### Generating Oauth Credentials

To obtain oauth credentials, follow below steps:

- Follow [Enable Drive API](#enable-drive-api) section.
- Open [google console](https://console.developers.google.com/).
- Click on "Credentials".
Expand All @@ -311,6 +322,24 @@ First, we need to obtain our oauth credentials, here's how to do it:

Now, we have obtained our credentials, move to the [First run](#first-run) section to use those credentials:

### Generating service account credentials

To obtain service account credentials, follow below steps:

- Follow [Enable Drive API](#enable-drive-api) section.
- Open [google console](https://console.developers.google.com/).
- Click on "Credentials".
- Click "Create credentials" and select "Service account".
- Provide name for service account and click on create. If successful, it should be on step 2.
- Now tap on role and select owner. Click on continue. If successful, it should be on step 3.
- Click on done.
- Now click on manage service accounts.
- Click on the service account name you created.
- Click on add key, then tap on create new key. Choose json and tap on create.
- If successful, a file should download in the .json format.

Now, we have obtained our service account json, move to the [First run](#first-run) section to use those credentials:

### Enable Drive API

- Log into google developer console at [google console](https://console.developers.google.com/).
Expand All @@ -331,28 +360,47 @@ By this, a side bar is opened. At there, select "API & Services" -> "Library". A

[Go back to oauth credentials setup](#generating-oauth-credentials)

[Go back to service account generation](#generating-service-account-credentials)

### First Run

On first run, there are two possibilities, either using oauth credentials or service account credentials.

#### For Oauth

On first run, the script asks for all the required credentials, which we have obtained in the previous section.

Execute the script: `gupload filename`

Now, it will ask for following credentials:

**Client ID:** Copy and paste from credentials.json
- **Client ID:** Copy and paste from credentials.json

**Client Secret:** Copy and paste from credentials.json
- **Client Secret:** Copy and paste from credentials.json

**Refresh Token:** If you have previously generated a refresh token authenticated to your account, then enter it, otherwise leave blank.
If you don't have refresh token, script outputs a URL on the terminal script, open that url in a web browser and tap on allow. Copy the code and paste in the terminal.
- **Refresh Token:** If you have previously generated a refresh token authenticated to your account, then enter it, otherwise leave blank.

**Root Folder:** Gdrive folder url/id from your account which you want to set as root folder. You can leave it blank and it takes `root` folder as default.
If you don't have refresh token, script outputs a URL on the terminal script, open that url in a web browser and tap on allow. Copy the code and paste in the terminal.

- **Root Folder:** Gdrive folder url/id from your account which you want to set as root folder. You can leave it blank and it takes `root` folder as default.

If everything went fine, all the required credentials have been set, read the next section on how to upload a file/folder.

#### For service accounts

For using service account, use `-sa | --service-account` flag.

Execute the script: `gupload filename -sa "service account json file path"`

Note: For service accounts it is necessary to use the `-sa | --service-account` flag everytime.

For more info, see `-sa | --service-account` flag in [Upload Script Custom Flags](#upload-script-custom-flags).

### Config

After first run, the credentials are saved in config file. By default, the config file is `${HOME}/.googledrive.conf`.
After first run, if oauth credentials are used, then credentials are saved in config file, otherwise for service accounts it is necessary to use the `-sa | --service-account` flag everytime.

By default, the config file is `${HOME}/.googledrive.conf`.

To change the default config file or use a different one temporarily, see `-z / --config` custom in [Upload Script Custom Flags](#upload-script-custom-flags).

Expand Down Expand Up @@ -410,6 +458,14 @@ Apart from basic usage, this script provides many flags for custom usecases, lik

These are the custom flags that are currently implemented:

- <strong>--sa | --service-accounts 'service account json file path'</strong>

Use a service account. Should be in proper json format.

To generate service accounts, see [service account generation](#generating-service-account-credentials) section.

---

- <strong>-z | --config</strong>

Override default config file with custom config file.
Expand Down
17 changes: 14 additions & 3 deletions bash/drive-utils.bash
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,22 @@ _extract_id() {
# Result: Update access_token and expiry else print error
###################################################
_get_access_token_and_update() {
RESPONSE="${1:-$(curl --compressed -s -X POST --data "client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&refresh_token=${REFRESH_TOKEN}&grant_type=refresh_token" "${TOKEN_URL}")}" || :
case "${1:?Error: sa or normal}" in
normal)
RESPONSE="${2:-$(curl --compressed -s -X POST --data "client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&refresh_token=${REFRESH_TOKEN}&grant_type=refresh_token" "${TOKEN_URL}")}" || :
;;
sa)
declare assertion_data="${2:?2lError: Missing assertion data.}"
RESPONSE="$(curl --compressed -s --data "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=${assertion_data}" "${TOKEN_URL}")" || :
# sa token jsons are not pretty printed
RESPONSE="${RESPONSE//,\"/$'\n'\"}"
;;
esac

if ACCESS_TOKEN="$(_json_value access_token 1 1 <<< "${RESPONSE}")"; then
ACCESS_TOKEN_EXPIRY="$(($(printf "%(%s)T\\n" "-1") + $(_json_value expires_in 1 1 <<< "${RESPONSE}") - 1))"
_update_config ACCESS_TOKEN "${ACCESS_TOKEN}" "${CONFIG}"
_update_config ACCESS_TOKEN_EXPIRY "${ACCESS_TOKEN_EXPIRY}" "${CONFIG}"
_update_config "${SERVICE_ACCOUNT:+${SERVICE_ACCOUNT}_}ACCESS_TOKEN" "${ACCESS_TOKEN}" "${CONFIG}"
_update_config "${SERVICE_ACCOUNT:+${SERVICE_ACCOUNT}_}ACCESS_TOKEN_EXPIRY" "${ACCESS_TOKEN_EXPIRY}" "${CONFIG}"
else
"${QUIET:-_print_center}" "justify" "Error: Something went wrong" ", printing error." "=" 1>&2
printf "%s\n" "${RESPONSE}" 1>&2
Expand Down
4 changes: 2 additions & 2 deletions bash/google-oauth2.bash
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ if [[ ${1} = create ]]; then
_clear_line 1 1>&2

REFRESH_TOKEN="$(_json_value refresh_token 1 1 <<< "${RESPONSE}" || :)"
if _get_access_token_and_update "${RESPONSE}"; then
if _get_access_token_and_update normal "${RESPONSE}"; then
_update_config REFRESH_TOKEN "${REFRESH_TOKEN}" "${CONFIG}"
printf "Access Token: %s\n" "${ACCESS_TOKEN}"
printf "Refresh Token: %s\n" "${REFRESH_TOKEN}"
Expand All @@ -123,7 +123,7 @@ if [[ ${1} = create ]]; then
elif [[ ${1} = refresh ]]; then
if [[ -n ${REFRESH_TOKEN} ]]; then
_print_center "justify" "Required credentials set." "="
{ _get_access_token_and_update && _clear_line 1; } || return 1
{ _get_access_token_and_update normal && _clear_line 1; } || return 1
printf "Access Token: %s\n" "${ACCESS_TOKEN}"
else
"${QUIET:-_print_center}" "normal" "Refresh Token not set" ", use ${0##*/} create to generate one." "="
Expand Down
Loading

0 comments on commit 1b6bd25

Please sign in to comment.