Git Product home page Git Product logo

gce_metadata_server's Issues

Token refresh causes concurrent access crash

Noticed that if the access_token in the local gcloud is stale and needs refreshing, a call to the

/computeMetadata/v1/instance/service-accounts/default/token

endpoint also causes the local gcloud instance to also ask for

/computeMetadata/v1/project/numeric-project-id

In the trace below, I only asked for the token which inturn called gcloud...which seems to itself ask for the numeric-project-id almost at precisely the same time (see socat output). Since the local gcloud already thinks its running on the GCE, it asks the metadata emulator itself again...(or atleast thats what i think is going on)

The concurrent request somehow blocks and causes a server crash.

One temp workaround is to launch via gunicorn (two workers default) and that seems to work much better.

TODO: figure out what is actually happening...

python gce_metadata_server.py 
2016-08-17 18:23:36,478 - INFO -  * Running on http://0.0.0.0:18080/
2016-08-17 18:23:40,601 - INFO - Requesting ServiceAccount : default/token
2016-08-17 18:23:40,602 - INFO - token not found in cache, refreshing..
2016-08-17 18:23:41,636 - INFO - Refreshing access_token
2016-08-17 18:23:41,861 - INFO - Display format "json()".
2016-08-17 18:23:41,865 - INFO - access_token: <<REDACTED>
2016-08-17 18:23:41,971 - INFO - 127.0.0.1 - - [17/Aug/2016 18:23:41] "GET /computeMetadata/v1/instance/service-accounts/default/token HTTP/1.1" 200 -
2016-08-17 18:23:41,974 - INFO - Requesting numeric project_id: 
2016-08-17 18:23:41,974 - INFO - numeric-project-id not found, refreshing..
Your active configuration is: [default]

2016-08-17 18:23:41,988 - INFO - Display format "config json()".
2016-08-17 18:23:42,046 - INFO - Display format "
          table(
            projectId:sort=101,
            name,
            projectNumber
          )
         value(projectNumber)".
2016-08-17 18:23:43,255 - INFO - Returning numeric project_id:REDACTED

2016-08-17 18:23:43,256 - INFO - 127.0.0.1 - - [17/Aug/2016 18:23:43] "GET /computeMetadata/v1/project/numeric-project-id HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 47882)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 651, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 710, in finish
    self.wfile.close()
  File "/usr/lib/python2.7/socket.py", line 279, in close
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------

socat output

$ sudo socat -vvv TCP4-LISTEN:80,fork TCP4:127.0.0.1:18080

> 2016/08/17 18:23:40.598025  length=171 from=0 to=170
GET /computeMetadata/v1/instance/service-accounts/default/token HTTP/1.1\r
User-Agent: curl/7.35.0\r
Host: metadata.google.internal\r
Accept: */*\r
Metadata-Flavor: Google\r
\r

> 2016/08/17 18:23:40.614052  length=197 from=0 to=196
GET /computeMetadata/v1/project/numeric-project-id HTTP/1.1\r
Accept-Encoding: identity\r
Host: metadata.google.internal\r
Metadata-Flavor: Google\r
Connection: close\r
User-Agent: Python-urllib/2.7\r
\r
< 2016/08/17 18:23:41.972111  length=17 from=0 to=16
HTTP/1.0 200 OK\r
< 2016/08/17 18:23:41.972352  length=53 from=17 to=69
Content-Type: application/json\r
Content-Length: 144\r
< 2016/08/17 18:23:41.972568  length=57 from=70 to=126
Server: Metadata Server for VM\r
Metadata-Flavor: Google\r
< 2016/08/17 18:23:41.972752  length=39 from=127 to=165
Date: Thu, 18 Aug 2016 01:23:41 GMT\r
\r
< 2016/08/17 18:23:41.972920  length=144 from=166 to=309
{
  "access_token": "<<REDACTED>>",
  "expires_in": 3600,
  "token_type": "Bearer"
}

Support curl --data-urlencode

When working with your metadata service, I've noticed that when using curl and the option --data-urlencode, it doesn't behave correctly and your mock responds

< HTTP/1.1 400 Bad Request
< Content-Type: text/plain; charset=utf-8
< Metadata-Flavor: Google
< Server: Metadata Server for VM
< X-Content-Type-Options: nosniff
< X-Frame-Options: 0
< X-Xss-Protection: 0
< Date: Sat, 27 Mar 2021 00:06:19 GMT
< Content-Length: 49
< 
Bad Request
* Connection #0 to host 127.0.0.1 left intact
non-empty audience parameter required%                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

Whereas when I'm talking directly the the google metadata service I get a proper response. My command line is as follows: curl -X GET --connect-to metadata.google.internal:80:127.0.0.1:8080 -v -H "Metadata-Flavor: Google" --data-urlencode "audience=https://vault/my-role" --data-urlencode "format=full" --data-urlencode format=full http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity

I receive a proper JWT token when using this command (minus the --connect-to portion because I don't need to override)

Using your mock, I have to actually append it to the URL: curl -X GET --connect-to metadata.google.internal:80:127.0.0.1:8080 -v -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity\?audience\=https://vault/my-role\&format\=full

The escapes are there because the CLI needs to escape shell characters.

Support generating required material to operate

In your documentation, you reference going to Google Cloud Platform and generating an actual service account. Not all situations require this kind of effort, nor would I want to actually use valid generated material in my mock.

It would be better if the service, when not provided ENV VARS or a service account json, to simply generate random material, or have a method to generate and run with random material.

I have tried supplying the ENV VARs with completely random material, however I got HTTP/500 errors so I'm presuming there's some kind of validation inside your mock.

Given the following format:

{
  "type": "service_account",
  "project_id": "[PROJECT]",
  "private_key_id": "[PRIVATE_KEY_ID]",
  "private_key": "-----BEGIN PRIVATE KEY-----\n[MATERIAL]\n...\n[MATERIAL]=\n-----END PRIVATE KEY-----\n",
  "client_email": "[CLIENT_NAME]@[PROJECT].iam.gserviceaccount.com",
  "client_id": "[CLIENT_ID]",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/[CLIENT_NAME]%[PROJECT].iam.gserviceaccount.com"
}

Surely something could be automatically generated so that we wouldn't require users to generate valid credential material right? The only other thing you'd need is a valid project id, and we'd be able to start the mock service. Is there a reason why this is required at all -- would think we would be able to run the mock without any of this period?

Implement 301 redirect for paths missing trailing /

We see a 301 redirect if we requests valid paths missing a tralining '/' as shown below

curl  -v -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts
* Hostname was NOT found in DNS cache
*   Trying 169.254.169.254...
* Connected to metadata.google.internal (169.254.169.254) port 80 (#0)
> GET /computeMetadata/v1/instance/service-accounts HTTP/1.1
> User-Agent: curl/7.38.0
> Host: metadata.google.internal
> Accept: */*
> Metadata-Flavor: Google
> 
< HTTP/1.1 301 Moved Permanently
< Metadata-Flavor: Google
< Location: http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/
< Date: Mon, 09 Jan 2017 19:19:20 GMT
< Content-Type: text/html
* Server Metadata Server for VM is not blacklisted
< Server: Metadata Server for VM
< Content-Length: 47
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< 
/computeMetadata/v1/instance/service-accounts/

Scopes of access_tokens are not quite the same as GCE

When requesting to secretsmanger with an access_token I receive:

Error fetching SLACK_SIGNING_SECRET: {
  "error": {
    "code": 403,
    "message": "Request had insufficient authentication scopes.",
    "status": "PERMISSION_DENIED"
  }
}

Where as the same request in prod gets:

Error fetching SLACK_SIGNING_SECRET: {
  "error": {
    "code": 403,
    "message": "Permission 'secretmanager.versions.access' denied for resource 'projects/XXX/secrets/SlackSigningSecret/versions/latest' (or it may not exist).",
    "status": "PERMISSION_DENIED"
  }
}

So I guess there is something wrong with the access token creations from the service account credentials I supplied

Idea: Support for Workload Identity Federation

I wonder if this server could be combined with the federated TokenSource providers in salrashid123/oauth2, to enable workloads running outside of Google Cloud to authenticate with a federated identity while using the ordinary Google Cloud libraries, as described in Accessing Resources from AWS.

The idea would be to have the metadata server serve up the access token produced by a configured TokenSource. For example, this would allow a pod running in EKS (with this server as a sidecar) to use its KSA to assume an AWS IAM role (as described here), and then impersonate a GSA, without any code changes. Does this seem reasonable?

Access to MetadataServer fake for go unit tests

As the currently stands, one can not use the MetadataServer for unit tests.

However, project can not import from main package. Also, it would be great to run the fake server from inside go test code, be able control what port the server binds on without having to run a compiled binary.

Is this something the repository maintainers could do ?

Container crash "Unable to verify OIDC token oidc: expected audience..."

I have two separate Cloud Run instances that I'm testing (not at exactly the same time per se). When I start up the metadata server container for the first time, I'm able to fetch an OAuth token (to authenticate service-to-service). But when I issue a new request with a different audience the apogiatzis/livereloading container crashes.

For example, I have two cloud run URL's (anonymizing for proprietary reasons):

Steps to reproduce

In docker-compose.yml I've defined:

version: '3'
services:
  proxy:
    build: nginx:mainline
    restart: always

  metadata.google.internal:
    image: salrashid123/gcemetadataserver
    container_name: metadata
    command: "-port :80
              --serviceAccountFile /conf/sa.json
              --tokenScopes https://www.googleapis.com/auth/cloud-platform
             "
    volumes:
      - .secret/:/conf/

In one window, run both containers, i.e. docker-compose up then in a new window, SSH into the proxy container via docker-compose exec proxy bash this is what happens:

root@301894f65b61:/# curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://app1-abcde12345.a.run.app
[LONG KEY OUTPUT HERE]

root@301894f65b61:/# curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://app2-vwxyz98765.a.run.app
curl: (52) Empty reply from server

Error output in the main docker-compose up window:

2020/06/18 03:39:48 salrashid123/oauth2/google: Unable to verify OIDC token oidc: expected audience "https://app1-abcde12345.a.run.app" got ["https://app2-vwxyz98765.a.run.app"]

static string after refactor

it's not clear how to pass a static string as the service token after the go refactor. is this something that is already implemented in the configuration of the google cloud go library's JSON file?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.