Verifying external access to a Data Share

Confirm that a Data Share is correctly set up and accessible to an external Data Consumer by exchanging the Client ID and Secret for a Knox access token and listing the shared Iceberg tables using the Cloudera Iceberg REST Catalog API.

After publishing a Data Share and distributing credentials to a Data Consumer, you can verify end-to-end access without a compute engine such as Spark, Snowflake, or Databricks. This procedure uses curl to perform two checks: it exchanges the Client ID and Secret for a short-lived Knox JWT access token, then uses that token to call the Cloudera Iceberg REST Catalog API and list the namespaces and tables that are visible to the consumer. Successful completion confirms that Knox credential exchange, Ranger authorization, and Iceberg REST routing are all functioning correctly for the Data Share.

  1. Set your environment variables from the credentials CSV file and your Data Lake details:
    CLIENT_ID="[***CLIENT-ID***]"
    CLIENT_SECRET="[***CLIENT-SECRET***]"
    
    DATALAKE_NAME="[***YOUR-DATALAKE-NAME***]"
    GATEWAY_HOST="[***DATALAKE-MASTER-HOSTNAME***]"
    TOPOLOGY="cdp-datashare-access"
    
    BASE_URL="https://${GATEWAY_HOST}/${DATALAKE_NAME}/${TOPOLOGY}"
    CLIENT_ID="e8a4239e-e3e2-4d3f-ba8d-3540ee4a895a"
    CLIENT_SECRET="WlRoaE5ES..."
    
    DATALAKE_NAME="cloudera-catalog-hue-lake-6"
    GATEWAY_HOST="cloudera-catalog-hue-lake-6-master0.cloudera.svbr-nqvp.int.cldr.work"
    TOPOLOGY="cdp-datashare-access"
    
    BASE_URL="https://cloudera-catalog-hue-lake-6-master0.cloudera.svbr-nqvp.int.cldr.work/cloudera-catalog-hue-lake-6/cdp-datashare-access"
  2. Request a Knox JWT access token by exchanging the Client ID and Secret:
    TOKEN_RESPONSE=$(curl -skS -X POST \
      -H "Content-Type: application/x-www-form-urlencoded" \
      --data-urlencode "grant_type=client_credentials" \
      --data-urlencode "client_id=${CLIENT_ID}" \
      --data-urlencode "client_secret=${CLIENT_SECRET}" \
      "${BASE_URL}/knoxtoken/api/v2/token")
    
    echo $TOKEN_RESPONSE | grep -o '"expires_in":[0-9]*' | cut -d':' -f2 | awk '{print int($1/1000)}' | xargs -I{} date -r {} "+Expires: %Y-%m-%d %H:%M:%S %Z"

    The expiry line confirms the token was issued and shows how long it is valid. For example: Expires: 2026-03-20 03:58:25 CET.

    Expires: 2026-03-20 04:12:38 CET

    A JSON response containing access_token and other fields confirms the credential exchange was successful.

  3. Extract the access token value into a variable:
    ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)

    Verify the token is a clean JWT string with no surrounding JSON:

    echo $ACCESS_TOKEN
    eyJqa3UiOiJodHRwczovL2Nsb3VkZXJhLWNhdGFs...
  4. Verify namespace access by listing all namespaces visible to the Data Consumer:
    curl -skS -u "Token:${ACCESS_TOKEN}" \
      "${BASE_URL}/iceberg-rest/v1/namespaces"

    Confirm that the namespace containing your shared Iceberg table appears in the response.

    {"namespaces":[["airline_operations"],["default"],["information_schema"],["sys"]]}
  5. List the tables in the target namespace to confirm the shared table is accessible:
    TARGET_NAMESPACE="[***TARGET-NAMESPACE***]"
    
    curl -skS -u "Token:${ACCESS_TOKEN}" \
      "${BASE_URL}/iceberg-rest/v1/namespaces/${TARGET_NAMESPACE}/tables"

    Verify that the shared Iceberg table name appears in the identifiers list of the response.

    {"identifiers":[{"namespace":["airline_operations"],"name":"enriched_flight_data"}]}
  6. Retrieve the table metadata to confirm schema access:
    TARGET_TABLE="[***TARGET-TABLE***]"
    
    curl -skS -u "Token:${ACCESS_TOKEN}" \
      "${BASE_URL}/iceberg-rest/v1/namespaces/${TARGET_NAMESPACE}/tables/${TARGET_TABLE}"

    The response contains the full Iceberg table metadata. Confirm that the metadata.schemas[0].fields array lists the expected columns, each with a name, type, and required field.

    {"metadata":{"schemas":[{"fields":[
      {"name":"flight_id","type":"string","required":false},
      {"name":"passenger_name","type":"string","required":false},
      {"name":"seat_assignment","type":"string","required":false},
      {"name":"aircraft_model","type":"string","required":false},
      {"name":"origin_airport","type":"string","required":false},
      {"name":"destination_airport","type":"string","required":false},
      {"name":"passenger_capacity","type":"integer","required":false},
      {"name":"age","type":"integer","required":false},
      {"name":"passport_number","type":"string","required":false}
    ]}]},...}

    A JSON response with populated metadata and metadata-location fields confirms that the Data Consumer can read the table schema. The Data Share is correctly set up and externally accessible.

The external consumer's Client ID and Secret are successfully exchanged for a Knox access token, and the Cloudera Iceberg REST Catalog confirms access to the shared namespace, table, and schema. The Data Share end-to-end verification is complete.

Once verified, the Data Consumer can configure their Iceberg REST Catalog compatible compute engine using the same Client ID and Secret. For an example using PySpark, see the Related information.