Skip to content

Instantly share code, notes, and snippets.

@testpilot031
Last active September 8, 2019 09:54
Show Gist options
  • Save testpilot031/e68f8a0f16ebbb3bb23003153588fb4d to your computer and use it in GitHub Desktop.
Save testpilot031/e68f8a0f16ebbb3bb23003153588fb4d to your computer and use it in GitHub Desktop.
Notes on executing GCP API with curl command

Overview

There are ways to use the gcloud API and SDK to run the GCP API.

Use a service account created with GCP. Since there is OAuth 2.0 authentication, API is accessed after getting a token. However, there was also a method of requesting the API directly without taking a token by encrypting the authentication information and embedding it in the http request header. I think that the latter is more familiar with how to make JWT, so this time I will use it.

The OS used was CentOS7 of Linux. In this article, we will skip creating service accounts. Please see https://jwt.io/introduction/ for details.

(Reference: Call using HTTP / REST https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests: How to call API directly https://developers.google.com/identity/protocols/OAuth2ServiceAccount#jwt-auth)

Google APIs GitHub repository seems to be unavailable if there is no API definition file you want to use. In this article, we will call the logging API. About logging API https://github.com/googleapis/googleapis/blob/master/google/logging/logging.yaml I was able to confirm it.

  1. Summarize the information required for authentication
  2. Create JSON Web Token (JWT) from 1.
  3. Calling GCP API using JWT

I want to call GCP API in curl like this.

1. Create authentication information (JWT)

Item Input Value
iss value of client_email in service account authentication file (JSON)
sub value of client_email in service account authentication file (JSON)
aud Create it like "https: // SERVICE_NAME / API_NAME". In this case, SERVICE_NAME and API_NAME are in https://github.com/googleapis/googleapis/blob/master/google/logging/logging.yaml.
iat The time when the assertion was issued. It is specified in seconds since January 1, 1970 00:00:00 UTC.
exp The expiration date of the assertion. Specified as the number of seconds since 00:00:00 UTC on January 1, 1970. This value is a maximum of one hour after the issue time. ** The token you create has an expiration date. The deadline is up to 1 hour. **
kid private_key_id in JSON of service account authentication information

Reference: https://developers.google.com/identity/protocols/OAuth2ServiceAccount

2. Create a JSON Web Token (hereinafter JWT) from 1.

Use Python 2.7.5. Install using pip.

python get-pip.py
pip install pyjwt
pip install cryptography

python code

Complete the python code based on the https://developers.google.com/identity/protocols/OAuth2ServiceAccount#jwt-auth code. ** signed_jwt ** is output, so copy it.

#-*-coding: utf-8-*-
import jwt
import time
iat = time.time ()
exp = iat + 3600
payload = {'iss': 'stackdriver-logging-read @ xxxxx-xxxxx-xxxx..iam.gserviceaccount.com',
     'sub': 'stackdriver-logging-read@xxxxx-xxxxx-xxxx.iam.gserviceaccount.com',
     'aud': 'https://logging.googleapis.com/google.logging.v2.LoggingServiceV2',
     'iat': iat,
     'exp': exp}
additional_headers = {'kid': 'XXXXXXXXXXXXX'}
signed_jwt = jwt.encode (payload, '----- BEGIN PRIVATE KEY ----- \ nXXXXXXXXXXXXXXXXXXXXXXXXXXX \ n ----- END PRIVATE KEY ----- \ n', headers = additional_headers, algorithm = ' RS256 ')
print signed_jwt

3. Calling GCP API using JWT

Check the GCP [manual page] (https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/list) for the URI to specify for curl, or use --log- If you run with http, you can see below.

gcloud logging read 'timestamp <= "2019-07-30T23: 59: 59Z"' --format = "json" --log-http
...
==== request start ====
uri: https://logging.googleapis.com/v2/entries:list?alt=json
method: POST
...

The curl command is as follows. Please put ** signed_jwt ** made with python and GCP project-name appropriately.

curl -X POST \
  'https://logging.googleapis.com/v2/entries:list?alt=json' \
  -H 'Authorization: Bearer <signed_jwt>' \
  -H 'Content-Type: application / json' \
  -H 'Host: logging.googleapis.com' \
  -d '{"filter":' \ '' timestamp <= "2019-07-30T23: 59: 59Z" '\' ', "orderBy": "timestamp desc", "pageSize": 1000, "resourceNames": ["projects / <project-name>"]} '
    1. As I wrote in the exp section of creating authentication information (JWT), the token has an expiration date. If it expires, you must create signed_jwt again. *

The output is as follows. Same as when executing gcloud command.

{
  "entries": [
    {
      "insertId": "............................. Aj_ ..",
      "jsonPayload": {
        "client.received.end.timestamp": "1564465946852",
        "request.verb": "GET",
...
`` `

## Supplement
JWT was generated with a python tool, but I also examined how to generate it with Linux commands

JWT
-Header
-Payload
-Signature
Consists of

base64UrlEncode (header) + "." + base64UrlEncode (payload) + "." + Signature

Signature is
base64UrlEncode (header) + "." + base64UrlEncode (payload)
Signed with a private key and base64UrlEncode.

The private key is in the GCP service account credentials (json).
A string starting with ----- BEGIN PRIVATE KEY -----. Copy this and create a text file (secret_key).

```shell

header = '{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "0123456789abcdef01234567"
} '
payload = '{
  "iss": "[email protected]",
  "iat": 1565869581.475549,
  "sub": "[email protected]",
  "exp": 1565873181.475549,
  "aud": "https://logging.googleapis.com/google.logging.v2.LoggingServiceV2"
} '
base64UrlEncHeader = `echo -n $ {header} | tr -d" \ n "| openssl base64 | tr-'+ / =' '-_' | tr -d" \ n "`
base64UrlEncPayload = `echo -n $ {payload} | tr -d" \ n "| openssl base64 | tr-'+ / =' '-_' | tr -d" \ n "`
signature = `echo -n" $ {base64UrlEncHeader}. $ {base64UrlEncPayload} "| openssl dgst -sha256 -sign secret_key -binary | openssl base64 | tr-'+ / =' '-_' | tr -d" \ n "`
echo "$ {base64UrlEncHeader}. $ {base64UrlEncPayload}. $ {signature}"

[reference] https://jwt.io/introduction/ https://qiita.com/kunichiko/items/3c0b1a2915e9dacbd4c1 https://crypto.stackexchange.com/posts/68400/revisions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment