Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OCI support #4518

Closed
carabasdaniel opened this issue Mar 30, 2022 · 11 comments
Closed

Add OCI support #4518

carabasdaniel opened this issue Mar 30, 2022 · 11 comments

Comments

@carabasdaniel
Copy link
Contributor

What part of OPA would you like to see improved?

We would like OPA to be able to consume bundles from an OCI registry. This integration will allow us to take advantage of the richness of the OCI ecosystem including but not limited to image signing, versioning, caching, layering, etc.

Describe the ideal solution

Ideally once this is implemented a user could use a configuration similar to the example below to consume a bundle from an OCI registry.

Example:

services:
  github-registry:
    url: https://ghcr.io
    type: oci
    credentials:
      username: alice
      password: secret

bundles:
  authz:
    service: github-registry
    resource: open-policy-agent/my-bundle:1.0.1
    persist: true
    polling:
      min_delay_seconds: 60
      max_delay_seconds: 120

# The local OCI store would be persisted to /var/opa/oci
persistence_directory: /var/opa

Additional Context

To implement this we thought we should create a downloader interface and implement an OCIDownloader - download.NewOCI(...). The current downloader can remain as the default http downloader.

To drive the implementation of the new OCIDownloader we would like to use ORAS as it would offer higher level constructs that are easier to implement with.

For additional details please consult the following document that was presented in the OPA community call.

@tsandall
Copy link
Member

tsandall commented Apr 2, 2022

Hi @carabasdaniel. Thanks for filing this issue. This topic has come up before over the years (e.g., #1464)

his integration will allow us to take advantage of the richness of the OCI ecosystem including but not limited to image signing, versioning, caching, layering, etc.

Could you elaborate on a few of these things?

  • how does image signing compare to the existing bundle signing mechanism we have in OPA?
  • what use cases are driving your versioning requirements and how are those not met by the existing bundle support?
  • what use cases are driving your need for layered filesystems that images are based on?
  • I'm assuming the caching benefit you described is related to layers but if not, please elaborate on how the existing HTTP-based caching mechanisms are lacking.

Overall, I'm in favour in adding OCI support to OPA for policy distribution, I just want to understand the motivation (beyond OCI being cool 😅 ).

The other thing to consider is the implementation and reliance on 3rdparty libraries. We're already starting to see difficulties due to the embedding of otel, wasmtime, and badger in OPA--if we use ORAS that would add another dependency; it looks like the oras-go package has a v1 release that promises stability, can the implementation rely on that?

EDIT: one more thing to consider... now that we have disk-store support in the server, we want to work on optimizing how data sets are loaded out of bundles and written into the store. One of the challenges there is to avoid paging all of the data into memory unnecessarily. We want to get away from deserializing the data sets into in-memory data structures unnecessarily. Whatever we do with the existing HTTP downloader will need to be done for the OCI downloader. This might influence whether we use ORAS or something else.

@carabasdaniel
Copy link
Contributor Author

carabasdaniel commented Apr 4, 2022

Hi @tsandall

how does image signing compare to the existing bundle signing mechanism we have in OPA?

According to their documentation, cosign offers support for:
- Hardware and KMS signing
- Bring-your-own PKI
- Our free OIDC PKI (Fulcio)
- Built-in binary transparency and timestamping service (Rekor)
As cosign is part of the sigstore project I think it makes sense to rely on this rich ecosystem for signing OCI artifacts, instead of using an internal implementation that only works for OPA.

e.g. as a security engineer, I'd like to be able to verify integrity of all OCI artifacts using the same tools

These two mechanisms don't need to be mutually exclusive though. It's possible to sign/verify layer contents using the current OPA mechanism as well.

what use cases are driving your versioning requirements and how are those not met by the existing bundle support?

Like any other artifact that we build and publish, we want to:

  1. Version it using semver (semver based on the API it's protecting)
  2. Distribution and consumption - here we prefer an OCI registry to a bucket store because they are ubiquitous. We can push to multiple vendors hassle free, as well as private registries.
  3. Be able to list in a human readable format, all the versions that have been published
  4. Be able to freeze a bundle in OPA to a particular version

These requirements are possible with http and the current bundle support, but they require investment in server side infrastructure, and at that point, you're building the features available in an OCI registry.

what use cases are driving your need for layered filesystems that images are based on?

Our current use case doesn't require multiple layers. The implementation we are using right now uses one layer per bundle. We don't have to use multiple layers in order to reap other benefits of the OCI ecosystem.

However, in the future we plan to use layers to easily manage different parts of a policy: manifest, rego specifications and data. And for data, you can imagine using child layers to only bring in changes to data, not update all of it.

I'm assuming the caching benefit you described is related to layers but if not, please elaborate on how the existing HTTP-based caching mechanisms are lacking.

The caching benefit is not related to layering in the sense that we'd only download changes from one version of a bundle to the next. The implementation of the local OCI store and its caching mechanism are very similar to what the HTTP implementation does. It uses the digest of a layer to determine whether it has to be downloaded or not (like the etag is currently used).
Here we mean that a disk-based cache is useful, so that we don't need to download bundles again on a restart of an OPA process.
But, as mentioned earlier, layering can help us in the future to only download changes.

I hope this clarifies a bit the motivation and I think this feature can open up multiple possibilities of improvements in the future.

@tsandall
Copy link
Member

tsandall commented Apr 7, 2022

@carabasdaniel thanks for the detailed response!

Another area that comes to mind (in addition to the disk storage integration that's still a bit of an unknown...) is incremental updates. OPA recently gained support for delta updates on data contained in the bundle. This is particularly useful for cases where the bundles are relatively large, but only small sets of data change--and where it's desirable to propagate that change quickly/efficiently.

How does OCI support incremental updates?

@carabasdaniel
Copy link
Contributor Author

Hi @tsandall,

With OCI, we'd have multiple layers, with each layer that is a child containing the delta from its parent. It sounds like the delta mechanism is there already, so this should work nicely. A layered approach can easily only grab new layers that contain new changes, and that would help with speed.

We'd like to implement this as a separate PR if that's ok, to get the basic functionality out there first. In the initial draft I put up, we're using a single layer approach to a bundle, and we currently still “feed” the tarball to the bundle loader directly. We'll have to test what this means for bundles that contain delta updates.

@tsandall
Copy link
Member

@carabasdaniel agreed we don't have to implement the functionality in the initial PR but it would be good to spec out how it would work so that we know we have that option in the future--otherwise we'd be adding something to OPA that we know will lead to scalability issues that will make users unhappy.

With OCI, we'd have multiple layers, with each layer that is a child containing the delta from its parent. It sounds like the delta mechanism is there already, so this should work nicely. A layered approach can easily only grab new layers that contain new changes, and that would help with speed.

It would be useful to spec out what the image contents would look like (format) and the network requests to fetch updates would look like (protocol) and call out any limitations, e.g., # of layers, that users would run into. E.g., suppose you have a bundle containing data for 100,000 resources/objects. If 1% of those objects change, what do the image layers look like and what do the network requests look like? What does it look like if another 1% change a few minutes later?

@carabasdaniel
Copy link
Contributor Author

Hi @tsandall,

It would be useful to spec out what the image contents would look like (format) and the network requests to fetch updates would look like (protocol) and call out any limitations, e.g., # of layers, that users would run into. E.g., suppose you have a bundle containing data for 100,000 resources/objects. If 1% of those objects change, what do the image layers look like and what do the network requests look like? What does it look like if another 1% change a few minutes later?

To get a better understanding can you please provide a few more details about the use case here?

  • Is it a mechanism to continuously (forever) feed data updates to OPA?

  • In OPA right now, if OPA restarts, how do I get back to my state? Do I have to consume all the deltas?

@tsandall
Copy link
Member

Is it a mechanism to continuously (forever) feed data updates to OPA?

Yes, that's how bundles have always worked--OPA periodically downloads the latest version of the bundle from the service that it's configured to talk to. Over time we've extended the bundle format and protocol to support deltas, long-polling, etc.

In OPA right now, if OPA restarts, how do I get back to my state? Do I have to consume all the deltas?

That's up to the bundle server--the format and protocol allow for the server to send a full snapshot or a snapshot and a sequence of deltas. IF OPA was using in-memory storage then the server would have to transmit the entire contents of the bundle; with OPA v0.39.0 we now have disk storage in the server and w/ the latest change to persist the ETag, OPA will send a network request w/ the ETag of the most recent bundle activation--in which case the server may not have to retransmit anything.

@viovanov
Copy link
Contributor

Hi @tsandall - we looked at the delta feature, and I don't think layers will be helpful for this use case.
It's not helpful to keep growing the number of layers in the image forever.
In this scenario, the behavior should remain as it is now.
The publisher of the bundle would replace the layer that opa downloads, with a delta bundle. (this works with the current PR)

srenatus pushed a commit that referenced this issue Apr 28, 2022
Initial support for #4518.

Configuration uses the 'services' config for registries, via the "type: oci" field.
Bundles configured to pull from that service will then use OCI.

```
services:
  ghcr-registry:
    url: https://ghcr.io
    type: oci
bundles:
  authz:
    service: ghcr-registry
    resource: ghcr.io/${ORGANIZATION}/${REPOSITORY}:${TAG}
    persist: true
    polling:
      min_delay_seconds: 60
      max_delay_seconds: 120
persistence_directory: ${PERSISTENCE_PATH}
```

Service credentials are supported: if you want to pull from a private registry,
use
```
services:
  ghcr-registry:
    url: https://ghcr.io
    type: oci
    credentials:
      bearer:
        token: ${GH_PAT}
```

If no `persistence_directory` is configured, the data is stored in a directory under /tmp.

See docs/devel/OCI.md for manual steps to test this feature with some
OCI registry (like ghcr.io).

Signed-off-by: carabasdaniel <dani@aserto.com>
damienjburks added a commit to damienjburks/opa that referenced this issue May 18, 2022
# This is the 1st commit message:

finalizing changes for formatting with sprintf

Signed-off-by: Damien Burks <damien@damienjburks.com>

# This is the commit message open-policy-agent#2:

updating changes to allow for multiple format strings

Signed-off-by: Damien Burks <damien@damienjburks.com>

# This is the commit message open-policy-agent#3:

fixing golint issues

Signed-off-by: Damien Burks <damien@damienjburks.com>

# This is the commit message open-policy-agent#4:

fixing golint issues

Signed-off-by: Damien Burks <damien@damienjburks.com>

# This is the commit message open-policy-agent#5:

making recommended change: package level variable

Signed-off-by: Damien Burks <damien@damienjburks.com>

# This is the commit message open-policy-agent#6:

adding support for explicit argument indexes

Signed-off-by: Damien Burks <damien@damienjburks.com>

# This is the commit message open-policy-agent#7:

format: don't add 'in' keyword import when 'every' is there (open-policy-agent#4607)

Also ensure that added imports have a location set.

Previously, `opa fmt` on the added test file would have panicked
because the import hadn't had a location.

Fixes open-policy-agent#4606.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#8:

ast+topdown+planner: allow for mocking built-in functions via "with" (open-policy-agent#4540)

With this change, we can replace calls to built-in functions via `with`. The replacement
can either be a value -- which will be used as the return value for every call to the
mocked built-in -- or a reference to a non-built-in function -- when the results need
to depend on the call's arguments.

Compiler, topdown, and planner have been adapted in this change. The included
docs changes describe the replacement options further.

Fixes first part of open-policy-agent#4449. (Missing are non-built-in functions as mock targets.)

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#9:

build(deps): bump google.golang.org/grpc from 1.45.0 to 1.46.0 (open-policy-agent#4617)


# This is the commit message open-policy-agent#10:

docs/policy-testing: use assignment operator in mocks (open-policy-agent#4618)

Additionally, simplify one test example.

Signed-off-by: Anders Eknert <anders@eknert.com>
# This is the commit message open-policy-agent#11:

cmd/capabilities: expose capabilities through CLI (open-policy-agent#4588)

There is a new command argument "capabilities". With this, it is
possible to print the current capabilities version, show all
capabilities versions & print any capabilities version, without the need
of a file. Moreover, for the other commands which use the --capabilities
flag, it is possible to give only the version number, without specifying
a file. However, there are no breaking changes for those who use the
capabilities file as an input for the flag. Unit tests were also
written, in order to test the new argument and the changes made in ast.

Fixes: open-policy-agent#4236

Signed-off-by: IoannisMatzaris <matzarisioannis@gmail.com>
# This is the commit message open-policy-agent#12:

format,eval: don't use source locations when formatting PE output (open-policy-agent#4611)

* format: allow ignoreing source locations
* cmd/eval: format disregarding source locations for partial result

Before, we'd see this output:
```
$ opa eval -p -fsource 'time.clock(input.x)==time.clock(input.y)'
# Query 1
time.clock(time.clock(input.x), input.y)
```

Now, we get the proper answer: `time.clock(input.y, time.clock(input.x))`.

Note that it's a _display_ issue; the JSON output of PE has not been affected.

Fixes open-policy-agent#4609.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#13:

build(deps): bump github/codeql-action from 1 to 2 (open-policy-agent#4621)

Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v1...v2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# This is the commit message open-policy-agent#14:

status: Remove activeRevision label on all but one metric (open-policy-agent#4600)

Having one activeRevision label on each of the prometheus metrics emitted
by the status plugin has proven to be problematic with a large number of
bundles. So with this change,

1. we keep the activeRevision label (just on) the last_success_bundle_activation metric.
2. the gauge gets reset, so we only keep the last active_revision (instead of keeping
   them all and therefore avoiding the situation where the /metrics output grows indefinitely)

Fixes open-policy-agent#4584.

Signed-off-by: cmuraru <cmuraru@adobe.com>
# This is the commit message open-policy-agent#15:

website: add playground button to navbar (open-policy-agent#4622)

Addressing one tiny bit of open-policy-agent#4614.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#16:

topdown/net: require prefix length for IPv6 in net.cidr_merge (open-policy-agent#4613)

There are no default prefixes in IPv6, so if an IPv6 without a prefix is fed into
net.cidr_merge, we'll return a non-halt error now.

Before, we'd fail in various ways if a prefix-less IPv6 was fed into
`net.cidr_merge`. With only one, we'd return `[ "<nil>" ]`, with two,
we'd panic.

Fixes open-policy-agent#4596.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#17:

Dockerfile: add source annotation (open-policy-agent#4626)

`org.opencontainers.image.source` URL to get source code for building the image (string)

https://github.com/opencontainers/image-spec/blob/main/annotations.md

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#18:

build(deps): bump github.com/fsnotify/fsnotify v1.5.2 -> v1.5.4 (open-policy-agent#4628)

https://github.com/fsnotify/fsnotify/releases/tag/v1.5.4

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#19:

docs: update version in kubernetes examples (open-policy-agent#4627)

Signed-off-by: yongen.pan <yongen.pan@daocloud.io>
# This is the commit message open-policy-agent#20:

bundle/status: Include bundle type in status information

OPA has support for Delta Bundles. The status object already
contains valuable information such as last activation timestamp but
does not specify if the bundle was a canonical snapshot or delta.

This change updates the bundle.Status object to include the
bundle type string: either "snapshot" or "delta". This can be useful
for status endpoints to differentiate between the bundle types.

Issue: 4477

Signed-off-by: Bryan Fulton <bryan@styra.com>

# This is the commit message open-policy-agent#21:

ast+topdown+planner: replacement of non-built-in functions via 'with' (open-policy-agent#4616)

Follow-up to open-policy-agent#4540

We can now mock functions that are user-defined:

    package test

    f(_) = 1 {
        input.x = "x"
    }
    p = y {
        y := f(1) with f as 2
    }

...following the same scoping rules as laid out for built-in mocks.
The replacement can be a value (replacing all calls), or a built-in,
or another non-built-in function.

Also addresses bugs in the previous slice:
* topdown/evalCall: account for empty rules result from indexer
* topdown/eval: capture value replacement in PE could panic

Note: in PE, we now drop 'with' for function mocks of any kind:

These are always fully replaced in the saved support modules, so
this should be OK.

When keeping them, we'd also have to either copy the existing definitions
into the support module; or create a function stub in it.

Fixes open-policy-agent#4449.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#22:

format: keep whitespaces for multiple indented same-line withs (open-policy-agent#4635)

Fixes open-policy-agent#4634.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#23:

downloader: support for downloading bundles from an OCI registry (open-policy-agent#4558)

Initial support for open-policy-agent#4518.

Configuration uses the 'services' config for registries, via the "type: oci" field.
Bundles configured to pull from that service will then use OCI.

```
services:
  ghcr-registry:
    url: https://ghcr.io
    type: oci
bundles:
  authz:
    service: ghcr-registry
    resource: ghcr.io/${ORGANIZATION}/${REPOSITORY}:${TAG}
    persist: true
    polling:
      min_delay_seconds: 60
      max_delay_seconds: 120
persistence_directory: ${PERSISTENCE_PATH}
```

Service credentials are supported: if you want to pull from a private registry,
use
```
services:
  ghcr-registry:
    url: https://ghcr.io
    type: oci
    credentials:
      bearer:
        token: ${GH_PAT}
```

If no `persistence_directory` is configured, the data is stored in a directory under /tmp.

See docs/devel/OCI.md for manual steps to test this feature with some
OCI registry (like ghcr.io).

Signed-off-by: carabasdaniel <dani@aserto.com>
# This is the commit message open-policy-agent#24:

Prepare v0.40.0 Release (open-policy-agent#4631)

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#25:

Prepare v0.41.0 development (open-policy-agent#4636)

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#26:

docs: Adding example for `rego.metadata.role()` usage (open-policy-agent#4640)

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
# This is the commit message open-policy-agent#27:

build(deps): bump oras.land/oras-go from 1.1.0 to 1.1.1 (open-policy-agent#4643)

Bumps [oras.land/oras-go](https://github.com/oras-project/oras-go) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/oras-project/oras-go/releases)
- [Commits](oras-project/oras-go@v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: oras.land/oras-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# This is the commit message open-policy-agent#28:

build(deps): bump OpenTelemetry 1.6.3 -> 1.7.0 (open-policy-agent#4649)

https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.7.0
https://github.com/open-telemetry/opentelemetry-go-contrib/releases/tag/v1.7.0

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#29:

build(deps): bump github.com/containerd/containerd from 1.6.2 to 1.6.3 (open-policy-agent#4654)

Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.6.2 to 1.6.3.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](containerd/containerd@v1.6.2...v1.6.3)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# This is the commit message open-policy-agent#30:

Update k8s examples to the latest schema (open-policy-agent#4655)

Signed-off-by: Víctor Martínez Bevià <vicmarbev@gmail.com>
# This is the commit message open-policy-agent#31:

Fix incorrect padding claims (open-policy-agent#4657)

Signed-off-by: Anders Eknert <anders@eknert.com>
# This is the commit message open-policy-agent#32:

build(deps): bump github.com/containerd/containerd from 1.6.3 to 1.6.4 (open-policy-agent#4662)

Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.6.3 to 1.6.4.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](containerd/containerd@v1.6.3...v1.6.4)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# This is the commit message open-policy-agent#33:

build(deps): bump docker/setup-qemu-action from 1 to 2 (open-policy-agent#4668)


# This is the commit message open-policy-agent#34:

build(deps): bump docker/setup-buildx-action from 1 to 2 (open-policy-agent#4669)

Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 2.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](docker/setup-buildx-action@v1...v2)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# This is the commit message open-policy-agent#35:

build(deps): github.com/bytecodealliance/wasmtime-go 0.35.0 -> 0.36.0 (open-policy-agent#4652)

* build(deps): bump wasmtime-go: 0.35.0 -> 0.36.0
* internal/wasm: adapt to using epoch-based interruption

Looks like we don't get frames for this.

Also, there is currentlty no better way than comparing the message,
as the trap code isn't surfaced (yet).

Fixes open-policy-agent#4663.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
# This is the commit message open-policy-agent#36:

ecosystem: Add Sansshell (open-policy-agent#4674)


Signed-off-by: James Chacon <james.chacon@snowflake.com>
# This is the commit message open-policy-agent#37:

topdown: Add units.parse builtin (open-policy-agent#4676)

This function works on all base decimal and binary SI units of the set:

    m, K/Ki, M/Mi, G/Gi, T/Ti, P/Pi, and E/Ei

Note: Unlike `units.parse_bytes`, this function is case sensitive.

Fixes open-policy-agent#1802.

Signed-off-by: Philip Conrad <philipaconrad@gmail.com>
# This is the commit message open-policy-agent#38:

docs/contrib-code: Add capabilities step to built-in functions tutorial (open-policy-agent#4677)

Signed-off-by: Philip Conrad <philipaconrad@gmail.com>
@stale
Copy link

stale bot commented May 19, 2022

This issue has been automatically marked as inactive because it has not had any activity in the last 30 days.

@stale stale bot added the inactive label May 19, 2022
@anderseknert
Copy link
Member

Can we close this and create follow-up issues for new features on top of what's there now?

@stale stale bot removed the inactive label May 19, 2022
@anderseknert
Copy link
Member

Closing this since we have at least basic support implemented, and there seems to be follow-up issues created as well. Let me know if I missed something and I'll re-open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants