When the discovery feature is enabled, OPA will periodically download a discovery bundle. Like regular bundles, the discovery bundle may contain JSON and Rego files. OPA will evaluate the data and policies contained in the discovery bundle to generate the rest of the configuration. There are two main ways to structure the discovery bundle:

  1. Include static JSON configuration files that define the OPA configuration.
  2. Include Rego files that can be evaluated to produce the OPA configuration.

If discovery is enabled, other features like bundle downloading and status reporting cannot be configured manually. Similarly, discovered configuration cannot override the original discovery settings in the configuration file that OPA was booted with.

See the Configuration Reference for configuration details.

OPA expects the service to expose an API endpoint that serves bundles.

If the bundle exists, the server should respond with an HTTP 200 OK status followed by a gzipped tarball in the message body.

  1. Content-Type: application/gzip

You can enable discovery with an OPA configuration file similar to the example below. In some places in the documentation, the initial configuration provided to OPA is referred to as the “boot configuration”.

  1. services:
  2. acmecorp:
  3. url: https://example.com/control-plane-api/v1
  4. credentials:
  5. bearer:
  6. token: "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm"
  7. discovery:
  8. service: acmecorp
  9. resource: /configuration/example/discovery.tar.gz

Using the boot configuration above, OPA will fetch discovery bundles from:

  1. https://example.com/control-plane-api/v1/configuration/example/discovery.tar.gz
  2. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  3. services[discovery.service].url discovery.resource
  1. services:
  2. - name: acmecorp
  3. url: https://example.com/control-plane-api/v1
  4. credentials:
  5. bearer:
  6. token: "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm"
  7. discovery:
  8. name: example
  9. resource: /configuration/example/discovery.tar.gz
  10. decision: example/discovery

OPA executes the following query:

If the discovery bundle contained the following Rego file:

  1. package example
  2. "bundles": {
  3. "main": {
  4. "service": "acmecorp",
  5. "resource": bundle_name
  6. },
  7. },
  8. }
  9. bundle_name = "acmecorp/httpauthz"

The subsequent configuration would be:

  1. {
  2. "bundles": {
  3. "main": {
  4. "service": "acmecorp",
  5. "resource": "acmecorp/httpauthz"
  6. },
  7. },
  8. "default_decision": "acmecorp/httpauthz/allow"
  9. }

The discovery bundle contents above are essentially static. The same result could be achieved by constructing the discovery bundle with a static JSON file:

  1. {
  2. "example": {
  3. "discovery": {
  4. "bundles": {
  5. "main": {
  6. "service": "acmecorp",
  7. "resource": "acmecorp/httpauthz"
  8. },
  9. },
  10. "default_decision": "acmecorp/httpauthz/allow"
  11. }
  12. }
  13. }

The subsequent configuration does not have to specify services or include a reference to a service in the bundle, status, or decision_log sections. If the either the services or references to services are missing, OPA will default them to the value from the boot configuration.

Let’s see an example of how the discovery feature can be used to dynamically configure an OPA to download one of two bundles based on a label in the boot configuration. Let’s say the label region indicates the region in which the OPA is running and it’s value will decide the bundle to download.

Below is a policy file which generates an OPA configuration.

example.rego

  1. config := {
  2. "bundles": {
  3. "main": {
  4. "service": "acmecorp",
  5. "resource": bundle_name # line 7
  6. }
  7. }
  8. }
  9. rt := opa.runtime()
  10. region := rt.config.labels.region
  11. bundle_name := region_bundle[region]
  12. # region-bundle information
  13. region_bundle := {
  14. "US": "example/test1/p",
  15. "UK": "example/test2/p"
  16. }

The bundle_name variable in line 7 of the above policy will be dynamically selected based on the value of the label region. So if an OPA was started with region: "US", then the bundle_name will be example/test1/p.

config.yaml

Run OPA:

  1. opa run -s -c config.yaml

You should see a log like below, which shows the bundle being downloaded. In this case, the bundle name is example/test1/p as region is US.

  1. INFO Bundle downloaded and activated successfully. name=example/test1/p plugin=bundle

Now start another OPA with a boot configuration as shown below. Notice the region is UK:

config.yaml

  1. services:
  2. - name: acmecorp
  3. url: https://example.com/control-plane-api/v1
  4. credentials:
  5. bearer:
  6. token: "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm"
  7. discovery:
  8. resource: bundles/discovery.tar.gz
  9. decision: discovery/config
  10. labels:
  11. region: "UK"

Run OPA:

    In this case, the bundle being downloaded is example/test2/p as region is UK.

    This shows how the discovery feature can help in centrally managing the bundle to be downloaded by an OPA based on a configuration label. You can use the same strategy to dynamically configure other plugins based on the running OPA’s configuration labels or environment variables.

    In practice, discovery services do not change frequently. These configuration sections are treated as immutable to avoid accidental configuration errors rendering OPA unable to discover a new configuration. If the discovered configuration changes the discovery or labels sections, those changes are ignored. If the discovered configuration changes the discovery service, an error will be logged.

    Like regular bundles, if the discovery bundle contains a .signatures.json file, OPA will verify the discovery bundle before activating it. The format of the .signatures.json file and the verification steps are same as that for regular bundles. Since the discovered configuration ignores changes to the section, any key used for signature verification of a discovery bundle CANNOT be modified via discovery.