Пример #1
0
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
                                 const grpc_httpcli_response *response) {
  size_t i;
  int port = 0;
  portreq *pr = arg;

  if (!response || response->status != 200) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    GPR_ASSERT(pr->retries < 10);
    pr->retries++;
    req.host = pr->server;
    req.path = "/get";
    gpr_log(GPR_DEBUG, "failed port pick from server: retrying");
    sleep(1);
    grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pollset, &req,
                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                     pr);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset));
  pr->port = port;
  grpc_pollset_kick(&pr->pollset, NULL);
  gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset));
}
Пример #2
0
static void test_get(int port) {
  grpc_httpcli_request req;
  char *host;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  g_done = 0;
  gpr_log(GPR_INFO, "test_get");

  gpr_asprintf(&host, "localhost:%d", port);
  gpr_log(GPR_INFO, "requesting from %s", host);

  memset(&req, 0, sizeof(req));
  req.host = host;
  req.path = "/get";
  req.handshaker = &grpc_httpcli_plaintext;

  grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15),
                   on_finish, (void *)42);
  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
  while (!g_done) {
    grpc_pollset_worker worker;
    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
    grpc_exec_ctx_finish(&exec_ctx);
    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
  }
  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
  gpr_free(host);
}
Пример #3
0
static int is_stack_running_on_compute_engine(void) {
  compute_engine_detector detector;
  grpc_httpcli_request request;

  /* The http call is local. If it takes more than one sec, it is for sure not
     on compute engine. */
  gpr_timespec max_detection_delay = {1, 0};

  gpr_mu_init(&detector.mu);
  gpr_cv_init(&detector.cv);
  detector.is_done = 0;
  detector.success = 0;

  memset(&request, 0, sizeof(grpc_httpcli_request));
  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
  request.path = "/";

  grpc_httpcli_get(&request, gpr_time_add(gpr_now(), max_detection_delay),
                   on_compute_engine_detection_http_response, &detector);

  /* Block until we get the response. This is not ideal but this should only be
     called once for the lifetime of the process by the default credentials. */
  gpr_mu_lock(&detector.mu);
  while (!detector.is_done) {
    gpr_cv_wait(&detector.cv, &detector.mu, gpr_inf_future);
  }
  gpr_mu_unlock(&detector.mu);

  gpr_mu_destroy(&detector.mu);
  gpr_cv_destroy(&detector.cv);
  return detector.success;
}
Пример #4
0
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
                                 grpc_error *error) {
  size_t i;
  int port = 0;
  portreq *pr = arg;
  int failed = 0;
  grpc_httpcli_response *response = &pr->response;

  if (error != GRPC_ERROR_NONE) {
    failed = 1;
    const char *msg = grpc_error_string(error);
    gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
    grpc_error_free_string(msg);
  } else if (response->status != 200) {
    failed = 1;
    gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
            response->status);
  }

  if (failed) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    GPR_ASSERT(pr->retries < 10);
    gpr_sleep_until(gpr_time_add(
        gpr_now(GPR_CLOCK_REALTIME),
        gpr_time_from_millis(
            (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
            GPR_TIMESPAN)));
    pr->retries++;
    req.host = pr->server;
    req.http.path = "/get";
    grpc_http_response_destroy(&pr->response);
    memset(&pr->response, 0, sizeof(pr->response));
    grpc_resource_quota *resource_quota =
        grpc_resource_quota_create("port_server_client/pick_retry");
    grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req,
                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
                     grpc_closure_create(got_port_from_server, pr),
                     &pr->response);
    grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(pr->mu);
  pr->port = port;
  GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
  gpr_mu_unlock(pr->mu);
}
Пример #5
0
static void compute_engine_fetch_oauth2(
    grpc_credentials_metadata_request *metadata_req,
    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
  grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
  grpc_httpcli_request request;
  memset(&request, 0, sizeof(grpc_httpcli_request));
  request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
  request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
  request.hdr_count = 1;
  request.hdrs = &header;
  grpc_httpcli_get(&request, deadline, response_cb, metadata_req);
}
Пример #6
0
static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
                                       grpc_error *error) {
  const grpc_json *cur;
  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
  const grpc_http_response *response = &ctx->responses[HTTP_RESPONSE_OPENID];
  grpc_json *json = json_from_http(response);
  grpc_httpcli_request req;
  const char *jwks_uri;

  /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */
  if (json == NULL) goto error;
  cur = find_property_by_name(json, "jwks_uri");
  if (cur == NULL) {
    gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
    goto error;
  }
  jwks_uri = validate_string_field(cur, "jwks_uri");
  if (jwks_uri == NULL) goto error;
  if (strstr(jwks_uri, "https://") != jwks_uri) {
    gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
    goto error;
  }
  jwks_uri += 8;
  req.handshaker = &grpc_httpcli_ssl;
  req.host = gpr_strdup(jwks_uri);
  req.http.path = strchr(jwks_uri, '/');
  if (req.http.path == NULL) {
    req.http.path = "";
  } else {
    *(req.host + (req.http.path - jwks_uri)) = '\0';
  }

  /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host
     channel. This would allow us to cancel an authentication query when under
     extreme memory pressure. */
  grpc_resource_quota *resource_quota =
      grpc_resource_quota_create("jwt_verifier");
  grpc_httpcli_get(
      exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
      grpc_closure_create(on_keys_retrieved, ctx),
      &ctx->responses[HTTP_RESPONSE_KEYS]);
  grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
  grpc_json_destroy(json);
  gpr_free(req.host);
  return;

error:
  if (json != NULL) grpc_json_destroy(json);
  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
  verifier_cb_ctx_destroy(ctx);
}
Пример #7
0
void grpc_free_port_using_server(char *server, int port) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  grpc_httpcli_response rsp;
  freereq pr;
  char *path;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_closure *shutdown_closure;

  grpc_init();

  memset(&pr, 0, sizeof(pr));
  memset(&req, 0, sizeof(req));
  memset(&rsp, 0, sizeof(rsp));

  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
  grpc_pollset_init(pollset, &pr.mu);
  pr.pops = grpc_polling_entity_create_from_pollset(pollset);
  shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops);

  req.host = server;
  gpr_asprintf(&path, "/drop/%d", port);
  req.http.path = path;

  grpc_httpcli_context_init(&context);
  grpc_resource_quota *resource_quota =
      grpc_resource_quota_create("port_server_client/free");
  grpc_httpcli_get(&exec_ctx, &context, &pr.pops, resource_quota, &req,
                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
                   grpc_closure_create(freed_port_from_server, &pr), &rsp);
  grpc_resource_quota_internal_unref(&exec_ctx, resource_quota);
  gpr_mu_lock(pr.mu);
  while (!pr.done) {
    grpc_pollset_worker *worker = NULL;
    if (!GRPC_LOG_IF_ERROR(
            "pollset_work",
            grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
                              GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
      pr.done = 1;
    }
  }
  gpr_mu_unlock(pr.mu);

  grpc_httpcli_context_destroy(&context);
  grpc_exec_ctx_finish(&exec_ctx);
  grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                        shutdown_closure);
  grpc_exec_ctx_finish(&exec_ctx);
  gpr_free(path);
  grpc_http_response_destroy(&rsp);
}
Пример #8
0
int grpc_pick_port_using_server(char *server) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  portreq pr;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_closure *shutdown_closure;

  grpc_init();

  memset(&pr, 0, sizeof(pr));
  memset(&req, 0, sizeof(req));
  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
  grpc_pollset_init(pollset, &pr.mu);
  pr.pops = grpc_polling_entity_create_from_pollset(pollset);
  shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops);
  pr.port = -1;
  pr.server = server;
  pr.ctx = &context;

  req.host = server;
  req.http.path = "/get";

  grpc_httpcli_context_init(&context);
  grpc_resource_quota *resource_quota =
      grpc_resource_quota_create("port_server_client/pick");
  grpc_httpcli_get(&exec_ctx, &context, &pr.pops, resource_quota, &req,
                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
                   grpc_closure_create(got_port_from_server, &pr),
                   &pr.response);
  grpc_resource_quota_internal_unref(&exec_ctx, resource_quota);
  grpc_exec_ctx_finish(&exec_ctx);
  gpr_mu_lock(pr.mu);
  while (pr.port == -1) {
    grpc_pollset_worker *worker = NULL;
    if (!GRPC_LOG_IF_ERROR(
            "pollset_work",
            grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
                              GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
      pr.port = 0;
    }
  }
  gpr_mu_unlock(pr.mu);

  grpc_http_response_destroy(&pr.response);
  grpc_httpcli_context_destroy(&context);
  grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                        shutdown_closure);
  grpc_exec_ctx_finish(&exec_ctx);

  return pr.port;
}
Пример #9
0
static void test_get(int use_ssl) {
  grpc_httpcli_request req;

  gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_get", use_ssl);

  gpr_event_init(&g_done);
  memset(&req, 0, sizeof(req));
  req.host = "www.google.com";
  req.path = "/";
  req.use_ssl = use_ssl;

  grpc_httpcli_get(&req, n_seconds_time(15), on_finish, (void *)42);
  GPR_ASSERT(gpr_event_wait(&g_done, n_seconds_time(20)));
}
Пример #10
0
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
                                 const grpc_httpcli_response *response) {
  size_t i;
  int port = 0;
  portreq *pr = arg;
  int failed = 0;

  if (!response) {
    failed = 1;
    gpr_log(GPR_DEBUG,
            "failed port pick from server: retrying [response=NULL]");
  } else if (response->status != 200) {
    failed = 1;
    gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
            response->status);
  }

  if (failed) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    GPR_ASSERT(pr->retries < 10);
    gpr_sleep_until(gpr_time_add(
        gpr_now(GPR_CLOCK_REALTIME),
        gpr_time_from_millis(
            (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
            GPR_TIMESPAN)));
    pr->retries++;
    req.host = pr->server;
    req.http.path = "/get";
    grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, &req,
                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                     pr);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(pr->mu);
  pr->port = port;
  grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL);
  gpr_mu_unlock(pr->mu);
}
Пример #11
0
static int is_stack_running_on_compute_engine(void) {
  compute_engine_detector detector;
  grpc_httpcli_request request;
  grpc_httpcli_context context;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_closure destroy_closure;

  /* The http call is local. If it takes more than one sec, it is for sure not
     on compute engine. */
  gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);

  grpc_pollset_init(&detector.pollset);
  detector.is_done = 0;
  detector.success = 0;

  memset(&request, 0, sizeof(grpc_httpcli_request));
  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
  request.path = "/";

  grpc_httpcli_context_init(&context);

  grpc_httpcli_get(
      &exec_ctx, &context, &detector.pollset, &request,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
      on_compute_engine_detection_http_response, &detector);

  grpc_exec_ctx_finish(&exec_ctx);

  /* Block until we get the response. This is not ideal but this should only be
     called once for the lifetime of the process by the default credentials. */
  gpr_mu_lock(GRPC_POLLSET_MU(&detector.pollset));
  while (!detector.is_done) {
    grpc_pollset_worker worker;
    grpc_pollset_work(&exec_ctx, &detector.pollset, &worker,
                      gpr_now(GPR_CLOCK_MONOTONIC),
                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
  }
  gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));

  grpc_httpcli_context_destroy(&context);
  grpc_closure_init(&destroy_closure, destroy_pollset, &detector.pollset);
  grpc_pollset_shutdown(&exec_ctx, &detector.pollset, &destroy_closure);
  grpc_exec_ctx_finish(&exec_ctx);

  return detector.success;
}
Пример #12
0
static void on_openid_config_retrieved(void *user_data,
                                       const grpc_httpcli_response *response) {
  const grpc_json *cur;
  grpc_json *json = json_from_http(response);
  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
  grpc_httpcli_request req;
  const char *jwks_uri;

  /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time.*/
  if (json == NULL) goto error;
  cur = find_property_by_name(json, "jwks_uri");
  if (cur == NULL) {
    gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
    goto error;
  }
  jwks_uri = validate_string_field(cur, "jwks_uri");
  if (jwks_uri == NULL) goto error;
  if (strstr(jwks_uri, "https://") != jwks_uri) {
    gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
    goto error;
  }
  jwks_uri += 8;
  req.use_ssl = 1;
  req.host = gpr_strdup(jwks_uri);
  req.path = strchr(jwks_uri, '/');
  if (req.path == NULL) {
    req.path = "";
  } else {
    *(req.host + (req.path - jwks_uri)) = '\0';
  }
  grpc_httpcli_get(
      &ctx->verifier->http_ctx, ctx->pollset, &req,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
      on_keys_retrieved, ctx);
  grpc_json_destroy(json);
  gpr_free(req.host);
  return;

error:
  if (json != NULL) grpc_json_destroy(json);
  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
  verifier_cb_ctx_destroy(ctx);
}
Пример #13
0
static int pick_port_using_server(char *server) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  portreq pr;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_closure shutdown_closure;

  grpc_init();

  memset(&pr, 0, sizeof(pr));
  memset(&req, 0, sizeof(req));
  pr.pollset = gpr_malloc(grpc_pollset_size());
  grpc_pollset_init(pr.pollset, &pr.mu);
  grpc_closure_init(&shutdown_closure, destroy_pollset_and_shutdown,
                    pr.pollset);
  pr.port = -1;
  pr.server = server;
  pr.ctx = &context;

  req.host = server;
  req.path = "/get";

  grpc_httpcli_context_init(&context);
  grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                   &pr);
  grpc_exec_ctx_finish(&exec_ctx);
  gpr_mu_lock(pr.mu);
  while (pr.port == -1) {
    grpc_pollset_worker *worker = NULL;
    grpc_pollset_work(&exec_ctx, pr.pollset, &worker,
                      gpr_now(GPR_CLOCK_MONOTONIC),
                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
  }
  gpr_mu_unlock(pr.mu);

  grpc_httpcli_context_destroy(&context);
  grpc_pollset_shutdown(&exec_ctx, pr.pollset, &shutdown_closure);
  grpc_exec_ctx_finish(&exec_ctx);
  gpr_free(pr.pollset);

  return pr.port;
}
Пример #14
0
static void free_port_using_server(char *server, int port) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  freereq pr;
  char *path;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_closure shutdown_closure;

  grpc_init();

  memset(&pr, 0, sizeof(pr));
  memset(&req, 0, sizeof(req));

  pr.pollset = gpr_malloc(grpc_pollset_size());
  grpc_pollset_init(pr.pollset, &pr.mu);
  grpc_closure_init(&shutdown_closure, destroy_pollset_and_shutdown,
                    pr.pollset);

  req.host = server;
  gpr_asprintf(&path, "/drop/%d", port);
  req.path = path;

  grpc_httpcli_context_init(&context);
  grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), freed_port_from_server,
                   &pr);
  gpr_mu_lock(pr.mu);
  while (!pr.done) {
    grpc_pollset_worker *worker = NULL;
    grpc_pollset_work(&exec_ctx, pr.pollset, &worker,
                      gpr_now(GPR_CLOCK_MONOTONIC),
                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
  }
  gpr_mu_unlock(pr.mu);

  grpc_httpcli_context_destroy(&context);
  grpc_exec_ctx_finish(&exec_ctx);
  grpc_pollset_shutdown(&exec_ctx, pr.pollset, &shutdown_closure);
  grpc_exec_ctx_finish(&exec_ctx);
  gpr_free(pr.pollset);
  gpr_free(path);
}
Пример #15
0
static void test_get(int port) {
  grpc_httpcli_request req;
  char *host;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  g_done = 0;
  gpr_log(GPR_INFO, "test_get");

  gpr_asprintf(&host, "localhost:%d", port);
  gpr_log(GPR_INFO, "requesting from %s", host);

  memset(&req, 0, sizeof(req));
  req.host = host;
  req.ssl_host_override = "foo.test.google.fr";
  req.http.path = "/get";
  req.handshaker = &grpc_httpcli_ssl;

  grpc_http_response response;
  memset(&response, 0, sizeof(response));
  grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_get");
  grpc_httpcli_get(
      &exec_ctx, &g_context, &g_pops, resource_quota, &req, n_seconds_time(15),
      grpc_closure_create(on_finish, &response, grpc_schedule_on_exec_ctx),
      &response);
  grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
  gpr_mu_lock(g_mu);
  while (!g_done) {
    grpc_pollset_worker *worker = NULL;
    GPR_ASSERT(GRPC_LOG_IF_ERROR(
        "pollset_work",
        grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
                          &worker, gpr_now(GPR_CLOCK_MONOTONIC),
                          n_seconds_time(20))));
    gpr_mu_unlock(g_mu);
    grpc_exec_ctx_finish(&exec_ctx);
    gpr_mu_lock(g_mu);
  }
  gpr_mu_unlock(g_mu);
  gpr_free(host);
  grpc_http_response_destroy(&response);
}
Пример #16
0
static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) {
  compute_engine_detector detector;
  grpc_httpcli_request request;
  grpc_httpcli_context context;
  grpc_closure destroy_closure;

  /* The http call is local. If it takes more than one sec, it is for sure not
     on compute engine. */
  gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);

  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
  grpc_pollset_init(pollset, &g_polling_mu);
  detector.pollent = grpc_polling_entity_create_from_pollset(pollset);
  detector.is_done = 0;
  detector.success = 0;

  memset(&detector.response, 0, sizeof(detector.response));
  memset(&request, 0, sizeof(grpc_httpcli_request));
  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
  request.http.path = "/";

  grpc_httpcli_context_init(&context);

  grpc_resource_quota *resource_quota =
      grpc_resource_quota_create("google_default_credentials");
  grpc_httpcli_get(
      exec_ctx, &context, &detector.pollent, resource_quota, &request,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
      grpc_closure_create(on_compute_engine_detection_http_response, &detector,
                          grpc_schedule_on_exec_ctx),
      &detector.response);
  grpc_resource_quota_unref_internal(exec_ctx, resource_quota);

  grpc_exec_ctx_flush(exec_ctx);

  /* Block until we get the response. This is not ideal but this should only be
     called once for the lifetime of the process by the default credentials. */
  gpr_mu_lock(g_polling_mu);
  while (!detector.is_done) {
    grpc_pollset_worker *worker = NULL;
    if (!GRPC_LOG_IF_ERROR(
            "pollset_work",
            grpc_pollset_work(exec_ctx,
                              grpc_polling_entity_pollset(&detector.pollent),
                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
                              gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
      detector.is_done = 1;
      detector.success = 0;
    }
  }
  gpr_mu_unlock(g_polling_mu);

  grpc_httpcli_context_destroy(exec_ctx, &context);
  grpc_closure_init(&destroy_closure, destroy_pollset,
                    grpc_polling_entity_pollset(&detector.pollent),
                    grpc_schedule_on_exec_ctx);
  grpc_pollset_shutdown(exec_ctx,
                        grpc_polling_entity_pollset(&detector.pollent),
                        &destroy_closure);
  g_polling_mu = NULL;
  grpc_exec_ctx_flush(exec_ctx);

  gpr_free(grpc_polling_entity_pollset(&detector.pollent));
  grpc_http_response_destroy(&detector.response);

  return detector.success;
}
Пример #17
0
/* Takes ownership of ctx. */
static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
                                    verifier_cb_ctx *ctx) {
  const char *at_sign;
  grpc_closure *http_cb;
  char *path_prefix = NULL;
  const char *iss;
  grpc_httpcli_request req;
  memset(&req, 0, sizeof(grpc_httpcli_request));
  req.handshaker = &grpc_httpcli_ssl;
  http_response_index rsp_idx;

  GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
  iss = ctx->claims->iss;
  if (ctx->header->kid == NULL) {
    gpr_log(GPR_ERROR, "Missing kid in jose header.");
    goto error;
  }
  if (iss == NULL) {
    gpr_log(GPR_ERROR, "Missing iss in claims.");
    goto error;
  }

  /* This code relies on:
     https://openid.net/specs/openid-connect-discovery-1_0.html
     Nobody seems to implement the account/email/webfinger part 2. of the spec
     so we will rely instead on email/url mappings if we detect such an issuer.
     Part 4, on the other hand is implemented by both google and salesforce. */

  /* Very non-sophisticated way to detect an email address. Should be good
     enough for now... */
  at_sign = strchr(iss, '@');
  if (at_sign != NULL) {
    email_key_mapping *mapping;
    const char *email_domain = at_sign + 1;
    GPR_ASSERT(ctx->verifier != NULL);
    mapping = verifier_get_mapping(ctx->verifier, email_domain);
    if (mapping == NULL) {
      gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
      goto error;
    }
    req.host = gpr_strdup(mapping->key_url_prefix);
    path_prefix = strchr(req.host, '/');
    if (path_prefix == NULL) {
      gpr_asprintf(&req.http.path, "/%s", iss);
    } else {
      *(path_prefix++) = '\0';
      gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss);
    }
    http_cb = grpc_closure_create(on_keys_retrieved, ctx);
    rsp_idx = HTTP_RESPONSE_KEYS;
  } else {
    req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
    path_prefix = strchr(req.host, '/');
    if (path_prefix == NULL) {
      req.http.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
    } else {
      *(path_prefix++) = 0;
      gpr_asprintf(&req.http.path, "/%s%s", path_prefix,
                   GRPC_OPENID_CONFIG_URL_SUFFIX);
    }
    http_cb = grpc_closure_create(on_openid_config_retrieved, ctx);
    rsp_idx = HTTP_RESPONSE_OPENID;
  }

  /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host
     channel. This would allow us to cancel an authentication query when under
     extreme memory pressure. */
  grpc_resource_quota *resource_quota =
      grpc_resource_quota_create("jwt_verifier");
  grpc_httpcli_get(
      exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
      http_cb, &ctx->responses[rsp_idx]);
  grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
  gpr_free(req.host);
  gpr_free(req.http.path);
  return;

error:
  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
  verifier_cb_ctx_destroy(ctx);
}
Пример #18
0
/* Takes ownership of ctx. */
static void retrieve_key_and_verify(verifier_cb_ctx *ctx) {
  const char *at_sign;
  grpc_httpcli_response_cb http_cb;
  char *path_prefix = NULL;
  const char *iss;
  grpc_httpcli_request req;
  memset(&req, 0, sizeof(grpc_httpcli_request));
  req.use_ssl = 1;

  GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
  iss = ctx->claims->iss;
  if (ctx->header->kid == NULL) {
    gpr_log(GPR_ERROR, "Missing kid in jose header.");
    goto error;
  }
  if (iss == NULL) {
    gpr_log(GPR_ERROR, "Missing iss in claims.");
    goto error;
  }

  /* This code relies on:
     https://openid.net/specs/openid-connect-discovery-1_0.html
     Nobody seems to implement the account/email/webfinger part 2. of the spec
     so we will rely instead on email/url mappings if we detect such an issuer.
     Part 4, on the other hand is implemented by both google and salesforce. */

  /* Very non-sophisticated way to detect an email address. Should be good
     enough for now... */
  at_sign = strchr(iss, '@');
  if (at_sign != NULL) {
    email_key_mapping *mapping;
    const char *email_domain = at_sign + 1;
    GPR_ASSERT(ctx->verifier != NULL);
    mapping = verifier_get_mapping(ctx->verifier, email_domain);
    if (mapping == NULL) {
      gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
      goto error;
    }
    req.host = gpr_strdup(mapping->key_url_prefix);
    path_prefix = strchr(req.host, '/');
    if (path_prefix == NULL) {
      gpr_asprintf(&req.path, "/%s", iss);
    } else {
      *(path_prefix++) = '\0';
      gpr_asprintf(&req.path, "/%s/%s", path_prefix, iss);
    }
    http_cb = on_keys_retrieved;
  } else {
    req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
    path_prefix = strchr(req.host, '/');
    if (path_prefix == NULL) {
      req.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
    } else {
      *(path_prefix++) = 0;
      gpr_asprintf(&req.path, "/%s%s", path_prefix,
                   GRPC_OPENID_CONFIG_URL_SUFFIX);
    }
    http_cb = on_openid_config_retrieved;
  }

  grpc_httpcli_get(
      &ctx->verifier->http_ctx, ctx->pollset, &req,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
      http_cb, ctx);
  gpr_free(req.host);
  gpr_free(req.path);
  return;

error:
  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
  verifier_cb_ctx_destroy(ctx);
}