Open hongbo-miao opened 2 years ago
Hey @Hongbo-Miao, you configured the callbacks to be sent to the OPAL server (you can actually send them to whatever server you choose).
Since OPAL server is running in secure mode, it requires that requests to its API will be provided with a bearer token (the client JWT token), and you did not provide a bearer token in your callback configuration.
The solution is very simple.
OPAL_CLIENT_TOKEN
.Assuming your client jwt token is MY_JWT
:
Your configuration should look like this:
OPAL_DEFAULT_UPDATE_CALLBACKS: '{"callbacks":[("http://opal-server-service.hm-opa:7002/data/callback_report",{"headers":{"Authorization":"Bearer MY_JWT"}})]}'
Oh, missed the headers
in OPAL_DEFAULT_UPDATE_CALLBACKS
.
I thought once having OPAL_CLIENT_TOKEN
, then no need.
Because we can still point to other servers, it makes sense!
Hi @asafc for better user experience, I actually think if we only provide OPAL_SHOULD_REPORT_ON_DATA_UPDATES=True
without OPAL_DEFAULT_UPDATE_CALLBACKS
, then it can point to opal-server by default.
That's a good idea, and in general I have big plans for OPAL usability :) We will soon move to a yaml based configuration with much better docs and sane defaults, which is more cloud-native-y and suitable for the kubernetes ecosystem.
Hmm, I was happy too early, I still have issue.
Here is my OPAL_DEFAULT_UPDATE_CALLBACKS
. You can see the token inside above is same with my OPAL_CLIENT_TOKEN
:
However, I still got
[2021-10-22 21:49:34 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2021-10-22 21:49:34 +0000] [1] [INFO] Listening at: http://0.0.0.0:7000 (1)
[2021-10-22 21:49:34 +0000] [1] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2021-10-22 21:49:34 +0000] [9] [INFO] Booting worker with pid: 9
2021-10-22T21:49:35.431731+0000 | opal_common.fetcher.fetcher_register | INFO | Loading FetcherProvider 'FastApiRpcFetchProvider' found at: <class 'opal_common.fetcher.providers.fastapi_rpc_fetch_provider.FastApiRpcFetchProvider'>
2021-10-22T21:49:35.432953+0000 | opal_common.fetcher.fetcher_register | INFO | Loading FetcherProvider 'HttpFetchProvider' found at: <class 'opal_common.fetcher.providers.http_fetch_provider.HttpFetchProvider'>
2021-10-22T21:49:35.460963+0000 | opal_common.fetcher.fetcher_register | INFO | Loading FetcherProvider 'PostgresFetchProvider' found at: <class 'opal_fetcher_postgres.provider.PostgresFetchProvider'>
2021-10-22T21:49:35.461154+0000 | opal_common.fetcher.fetcher_register | INFO | Fetcher Register loaded
2021-10-22T21:49:35.462163+0000 | opal_client.callbacks.register | INFO | Callbacks register loaded
2021-10-22T21:49:35.462503+0000 | opal_client.client | INFO | API authentication disabled (public encryption key was not provided)
2021-10-22T21:49:35.506748+0000 | uvicorn.server | INFO | Started server process [9]
2021-10-22T21:49:35.506914+0000 | uvicorn.lifespan.on | INFO | Waiting for application startup.
2021-10-22T21:49:35.507113+0000 | opal_client.opa.runner | INFO | Launching opa runner
2021-10-22T21:49:35.507249+0000 | uvicorn.lifespan.on | INFO | Application startup complete.
2021-10-22T21:49:35.509496+0000 | opal_client.opa.runner | INFO | Running OPA inline: opa run --server --addr=:8181 --authentication=off --authorization=off --config-file=/data/opa/config.yaml --log-level=info
2021-10-22T21:49:35.533237+0000 | opal_client.opa.logger | INFO | Initializing server. {'addrs': [':8181'], 'diagnostic-addrs': [], 'time': '2021-10-22T21:49:35Z'}
2021-10-22T21:49:35.534107+0000 | opal_client.opa.logger | INFO | Starting decision logger. {'plugin': 'decision_logs', 'time': '2021-10-22T21:49:35Z'}
2021-10-22T21:49:36.515751+0000 | opal_client.opa.runner | INFO | Running OPA initial start callbacks
2021-10-22T21:49:36.516605+0000 | opal_client.policy_store.opa_client | INFO | persisting health check policy: ready=false, healthy=false
2021-10-22T21:49:36.519933+0000 | opal_client.opa.logger | INFO | Received request. {'client_addr': '[::1]:41718', 'req_id': 1, 'req_method': 'PUT', 'req_path': '/v1/policies/opa/healthcheck/opal.rego', 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.521234+0000 | opal_client.opa.logger | INFO | Sent response. {'client_addr': '[::1]:41718', 'req_id': 1, 'req_method': 'PUT', 'req_path': '/v1/policies/opa/healthcheck/opal.rego', 'resp_bytes': 2, 'resp_duration': 1.3585, 'resp_status': 200, 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.522459+0000 | opal_client.data.updater | INFO | Launching data updater
2021-10-22T21:49:36.522656+0000 | opal_client.policy.updater | INFO | Launching policy updater
2021-10-22T21:49:36.522757+0000 | opal_client.data.updater | INFO | Subscribing to topics: ['policy_data']
2021-10-22T21:49:36.522958+0000 | opal_client.policy.updater | INFO | Subscribing to topics: ['policy:.']
2021-10-22T21:49:36.523243+0000 | fastapi_websocket_pubsub.pub_sub_client | INFO | Trying to connect to Pub/Sub server - ws://opal-server-service.hm-opa:7002/ws
2021-10-22T21:49:36.523601+0000 | fastapi_websocket_rpc.websocket_rpc_c...| INFO | Trying server - ws://opal-server-service.hm-opa:7002/ws
2021-10-22T21:49:36.526468+0000 | fastapi_websocket_pubsub.pub_sub_client | INFO | Trying to connect to Pub/Sub server - ws://opal-server-service.hm-opa:7002/ws
2021-10-22T21:49:36.526750+0000 | fastapi_websocket_rpc.websocket_rpc_c...| INFO | Trying server - ws://opal-server-service.hm-opa:7002/ws
2021-10-22T21:49:36.588082+0000 | opal_client.data.updater | INFO | Connected to server
2021-10-22T21:49:36.588235+0000 | opal_client.data.updater | INFO | Performing data configuration, reason: Initial load
2021-10-22T21:49:36.588487+0000 | opal_client.data.updater | INFO | Getting data-sources configuration from 'http://opal-server-service.hm-opa:7002/data/config'
2021-10-22T21:49:36.597174+0000 | opal_client.data.updater | INFO | Triggering data update with id: 4161dbc4465d48dd869157022fd91cdb
2021-10-22T21:49:36.597429+0000 | opal_client.data.updater | INFO | Fetching policy data
2021-10-22T21:49:36.597797+0000 | opal_client.data.fetcher | INFO | Fetching data from url: postgresql://admin@opa-db-service.hm-opa:40072/opa_db
2021-10-22T21:49:36.615697+0000 | fastapi_websocket_pubsub.pub_sub_client | INFO | Connected to PubSub server ws://opal-server-service.hm-opa:7002/ws
2021-10-22T21:49:36.685550+0000 | opal_client.policy.updater | INFO | Connected to server
2021-10-22T21:49:36.685856+0000 | opal_client.policy.updater | INFO | Refetching policy code (full bundle)
2021-10-22T21:49:36.695059+0000 | opal_client.data.updater | INFO | Saving fetched data to policy-store: source url='postgresql://admin@opa-db-service.hm-opa:40072/opa_db', destination path='/roles'
2021-10-22T21:49:36.700004+0000 | opal_client.opa.logger | INFO | Received request. {'client_addr': '[::1]:41734', 'req_id': 2, 'req_method': 'PUT', 'req_path': '/v1/data/roles', 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.701573+0000 | opal_client.opa.logger | INFO | Sent response. {'client_addr': '[::1]:41734', 'req_id': 2, 'req_method': 'PUT', 'req_path': '/v1/data/roles', 'resp_bytes': 0, 'resp_duration': 0.3013, 'resp_status': 204, 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.702588+0000 | opal_client.policy_store.opa_client | INFO | processing store transaction: {'id': '4161dbc4465d48dd869157022fd91cdb', 'actions': ['set_policy_data'], 'success': True, 'error': ''}
2021-10-22T21:49:36.702711+0000 | opal_client.policy_store.opa_client | INFO | persisting health check policy: ready=false, healthy=false
2021-10-22T21:49:36.707346+0000 | opal_client.opa.logger | INFO | Received request. {'client_addr': '[::1]:41736', 'req_id': 3, 'req_method': 'PUT', 'req_path': '/v1/policies/opa/healthcheck/opal.rego', 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.709756+0000 | opal_client.opa.logger | INFO | Sent response. {'client_addr': '[::1]:41736', 'req_id': 3, 'req_method': 'PUT', 'req_path': '/v1/policies/opa/healthcheck/opal.rego', 'resp_bytes': 2, 'resp_duration': 2.0526, 'resp_status': 200, 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.711007+0000 | opal_client.callbacks.reporter | INFO | Reporting the update to requested callbacks
2021-10-22T21:49:36.711655+0000 | opal_client.data.fetcher | INFO | Fetching data from url: http://opal-server-service.hm-opa:7002/data/callback_report
2021-10-22T21:49:36.714894+0000 | opal_client.policy.updater | INFO | Got policy bundle with 1 rego files, 0 data files, commit hash: '910d43e7e4da262d838c562ce3ae9910600fe445'
2021-10-22T21:49:36.717767+0000 | opal_client.opa.logger | INFO | Received request. {'client_addr': '[::1]:41740', 'req_id': 4, 'req_method': 'GET', 'req_path': '/v1/policies', 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.719894+0000 | opal_client.callbacks.reporter |ERROR | Failed to send report to http://opal-server-service.hm-opa:7002/data/callback_report, got response code 401 with error: {'detail': {'error': 'access token was not provided', 'token': None}}
2021-10-22T21:49:36.723232+0000 | opal_client.opa.logger | INFO | Sent response. {'client_addr': '[::1]:41740', 'req_id': 4, 'req_method': 'GET', 'req_path': '/v1/policies', 'resp_bytes': 5056, 'resp_duration': 5.1659, 'resp_status': 200, 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.726057+0000 | opal_client.opa.logger | INFO | Received request. {'client_addr': '[::1]:41742', 'req_id': 5, 'req_method': 'PUT', 'req_path': '/v1/policies/rbac.rego', 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.728361+0000 | opal_client.opa.logger | INFO | Sent response. {'client_addr': '[::1]:41742', 'req_id': 5, 'req_method': 'PUT', 'req_path': '/v1/policies/rbac.rego', 'resp_bytes': 2, 'resp_duration': 2.3008, 'resp_status': 200, 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.729521+0000 | opal_client.policy_store.opa_client | INFO | processing store transaction: {'id': '910d43e7e4da262d838c562ce3ae9910600fe445', 'actions': ['set_policies'], 'success': True, 'error': ''}
2021-10-22T21:49:36.729683+0000 | opal_client.policy_store.opa_client | INFO | persisting health check policy: ready=true, healthy=true
2021-10-22T21:49:36.731456+0000 | opal_client.callbacks.reporter | INFO | Reporting the update to requested callbacks
2021-10-22T21:49:36.731769+0000 | opal_client.data.fetcher | INFO | Fetching data from url: http://opal-server-service.hm-opa:7002/data/callback_report
2021-10-22T21:49:36.734616+0000 | opal_client.opa.logger | INFO | Received request. {'client_addr': '[::1]:41744', 'req_id': 6, 'req_method': 'PUT', 'req_path': '/v1/policies/opa/healthcheck/opal.rego', 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.738409+0000 | opal_client.opa.logger | INFO | Sent response. {'client_addr': '[::1]:41744', 'req_id': 6, 'req_method': 'PUT', 'req_path': '/v1/policies/opa/healthcheck/opal.rego', 'resp_bytes': 2, 'resp_duration': 3.7296, 'resp_status': 200, 'time': '2021-10-22T21:49:36Z'}
2021-10-22T21:49:36.741288+0000 | fastapi_websocket_pubsub.pub_sub_client | INFO | Connected to PubSub server ws://opal-server-service.hm-opa:7002/ws
2021-10-22T21:49:36.747092+0000 | opal_client.callbacks.reporter |ERROR | Failed to send report to http://opal-server-service.hm-opa:7002/data/callback_report, got response code 401 with error: {'detail': {'error': 'access token was not provided', 'token': None}}
Hey @Hongbo-Miao, you are right, we have a bug in 0.1.16 with Pydantic model unpacking of OPAL_DEFAULT_UPDATE_CALLBACKS
, thanks for reporting!! :)
I was not able to fix it on the fly (will keep this issue open), but i have a quick workaround for you.
use this configuration values instead:
(you simply move the callback http config to a different config var - OPAL_DEFAULT_UPDATE_CALLBACK_CONFIG
)
opal_client:
...
environment:
...
- OPAL_CLIENT_TOKEN=MY_CLIENT_JWT_TOKEN
- OPAL_DEFAULT_UPDATE_CALLBACKS={"callbacks":["http://opal_server:7002/data/callback_report"]}
- OPAL_DEFAULT_UPDATE_CALLBACK_CONFIG={"method":"post","headers":{"Authorization":"Bearer MY_CLIENT_JWT_TOKEN","content-type":"application/json"},"process_data":"false"}
My full configuration ahead for completeness of the answer (i used volumes for ssh keys for speed, but you can just put the actual public and private key inline as you always do):
version: "3.8"
services:
# When scaling the opal-server to multiple nodes and/or multiple workers, we use
# a *broadcast* channel to sync between all the instances of opal-server.
# Under the hood, this channel is implemented by encode/broadcaster (see link below).
# At the moment, the broadcast channel can be either: postgresdb, redis or kafka.
# The format of the broadcaster URI string (the one we pass to opal server as `OPAL_BROADCAST_URI`) is specified here:
# https://github.com/encode/broadcaster#available-backends
broadcast_channel:
image: postgres:alpine
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
opal_server:
# by default we run opal-server from latest official image
image: authorizon/opal-server:next
environment:
# the broadcast backbone uri used by opal server workers (see comments above for: broadcast_channel)
- OPAL_BROADCAST_URI=postgres://postgres:postgres@broadcast_channel:5432/postgres
# number of uvicorn workers to run inside the opal-server container
- UVICORN_NUM_WORKERS=4
# the git repo hosting our policy
# - if this repo is not public, you can pass an ssh key via `OPAL_POLICY_REPO_SSH_KEY`)
# - the repo we pass in this example is *public* and acts as an example repo with dummy rego policy
# - for more info, see: https://github.com/authorizon/opal/blob/master/docs/HOWTO/track_a_git_repo.md
- OPAL_POLICY_REPO_URL=https://github.com/authorizon/opal-example-policy-repo
# in this example we will use a polling interval of 30 seconds to check for new policy updates (git commits affecting the rego policy).
# however, it is better to utilize a git *webhook* to trigger the server to check for changes only when the repo has new commits.
# for more info see: https://github.com/authorizon/opal/blob/master/docs/HOWTO/track_a_git_repo.md
- OPAL_POLICY_REPO_POLLING_INTERVAL=30
# configures from where the opal client should initially fetch data (when it first goes up, after disconnection, etc).
# the data sources represents from where the opal clients should get a "complete picture" of the data they need.
# after the initial sources are fetched, the client will subscribe only to update notifications sent by the server.
- OPAL_DATA_CONFIG_SOURCES={"config":{"entries":[{"url":"http://opal_server:7002/policy-data","config":{"headers":{"Authorization":"Bearer MY_CLIENT_JWT_TOKEN"}},"topics":["policy_data"]}]}}
- OPAL_LOG_FORMAT_INCLUDE_PID=true
- OPAL_AUTH_PUBLIC_KEY=/var/secrets/opal_rsa.pub
- OPAL_AUTH_PRIVATE_KEY=/var/secrets/opal_rsa
- OPAL_AUTH_MASTER_TOKEN=secret
ports:
# exposes opal server on the host machine, you can access the server at: http://localhost:7002
- "7002:7002"
volumes:
- ~/.ssh:/var/secrets
depends_on:
- broadcast_channel
opal_client:
# by default we run opal-client from latest official image
image: authorizon/opal-client:next
environment:
- OPAL_SERVER_URL=http://opal_server:7002
- OPAL_CLIENT_TOKEN=MY_CLIENT_JWT_TOKEN
- OPAL_LOG_FORMAT_INCLUDE_PID=true
- OPAL_INLINE_OPA_LOG_FORMAT=http
# update callbacks config ----------------------------------
# this var turns on a callback (HTTP call to a configurable url) after every successful data update
# and allows you to track which data updates completed successfully and were saved to OPA cache.
- OPAL_SHOULD_REPORT_ON_DATA_UPDATES=True
# we configure a callback to go to a default location in the OPAL server, but you can configure
# a callback to any url you'd like. Each callback is either the url alone, or a tuple of
# (url, HttpFetcherConfig).
# We show here both ways to configure the same endpoint, one of them demonstrate how to
# add extra HTTP headers (the header shown is ignored, only here for example).
- OPAL_DEFAULT_UPDATE_CALLBACKS={"callbacks":["http://opal_server:7002/data/callback_report"]}
- OPAL_DEFAULT_UPDATE_CALLBACK_CONFIG={"method":"post","headers":{"Authorization":"Bearer MY_CLIENT_JWT_TOKEN","content-type":"application/json"},"process_data":"false"}
# OPAL can load a special policy into OPA that acts as a healthcheck policy (Not directly related to the callback feature).
# This policy defines two opa rules you can query:
# ready rule (POST http://localhost:8181/data/system/opal/ready): signals that OPA is ready to accept authorization queries.
# healthy rule (POST http://localhost:8181/data/system/opal/ready): signals that the last policy and data updates succeeded.
- OPAL_OPA_HEALTH_CHECK_POLICY_ENABLED=True
# end of update callbacks config ---------------------------
ports:
# exposes opal client on the host machine, you can access the client at: http://localhost:7000
- "7000:7000"
# exposes the OPA agent (being run by OPAL) on the host machine
# you can access the OPA api that you know and love at: http://localhost:8181
# OPA api docs are at: https://www.openpolicyagent.org/docs/latest/rest-api/
- "8181:8181"
depends_on:
- opal_server
# this command is not necessary when deploying OPAL for real, it is simply a trick for dev environments
# to make sure that opal-server is already up before starting the client.
command: sh -c "/usr/wait-for.sh opal_server:7002 --timeout=20 -- /start.sh"
Btw, found another bug while investigating this: already have outstanding pull with #168 and will merge on Sunday.
I have successfully set up the JWT token. This is my opal-client log which shows it works well.
Now I added
However, my opal-client failed to report the update to opal-server.
Both my opal-client and opal-server versions are 0.1.16.