This repository implements a common inventory system with eventing.
- Go 1.23.1+
- Make
When running locally, the default settings file is used. By default, this configuration does the following:
- Exposes the inventory API in
localhostand using port8000for http and port9000for grpc. - Sets authentication mechanism to
allow-unauthenticated, allowing users to be authenticated with their user-agent value. - Sets authorization mechanism to
allow-all. - Configures eventing mechanism to go to stdout.
- Sets database implementation to sqlite3 and the database file to
inventory.db - Configures log level to
INFO.
NOTE: You can update the default settings file as required to test different scenarios. Refer to the command line help (make run-help)
for information on the different parameters.
-
Clone the repository and navigate to the directory.
-
Install the required dependencies
make init
-
Build the project
# when building locally, use the local-build option as FIPS_ENABLED is set by default for builds make local-build -
Run the database migration
make migrate
-
Start the development server
make run
Due to various alternatives to running some images, we accept some arguments to override certain tools
Since there are official instructions on how to manage multiple installs
We accept the GO parameter when running make. e.g.
GO=go1.23.1 make runor
export GO=go1.23.1
make runWe will use podman if it is installed, and we will fall back to docker. You can also specify if you want to ensure a particular binary is used
by providing DOCKER parameter e.g.
DOCKER=docker make apior
export DOCKER=docker
make apiNote: The
podman-composeprovider struggles with compose files that leveragedepends_onas it can't properly handle the dependency graphs. You can fix this issue on Linux by installing thedocker-compose-pluginor also havingdocker-composeinstalled. When installed, podman uses thedocker-composeprovider by default instead. The benefit of thedocker-compose-pluginis that it doesn't require the full Docker setup or docker daemon!
See DEBUG for instructions on how to debug
In order to test Kessel Inventory with Kessel Relations, we recommend cloning the Relations API repo locally and leveraging their existing Docker Compose process to spin up the Relations API.
Both Inventory and Relations compose files are configured to use the same docker network (kessel) to ensure network connectivity between all containers.
For the Inventory Compose deployment:
- A PSK file is provided with the token "1234".
- Default ports in this setup are
8081for http and9091for grpc to not conflict with Relations - Refer to inventory-api-compose.yaml for additional configuration
To start use:
make inventory-upTo stop use:
make inventory-downInventory and Relations can also be run locally using built binaries, but the default config for Inventory will conflict with Relations.
To run Relations locally, see the Relations README
Relations will also require SpiceDB, this can be run using Podman/Docker (See relevant section also in the Relations README)
For Inventory, an alternate config is available, pre-configured to expect a local running Relations API
# Setup
make local-build
make migrate
# run with the relations friendly config file
./bin/inventory-api serve --config config/inventory-w-relations.yamlIn order to use the kafka configuration, one has to run strimzi and zookeeper. You can do this by running;
make inventory-up-kafkaStart Kessel Inventory and configuring it to connect to kafka:
eventing:
eventer: kafka
kafka:
bootstrap-servers: "localhost:9092"
# Adapt as required
# security-protocol: "SASL_PLAINTEXT"
# sasl-mechanism: PLAINYou can use our default config with kafka by running:
INVENTORY_API_CONFIG="./kafka-inventory-api.yaml" make run- Refer to kafka-inventory-api.yaml for additional configuration
Once started, you can watch the messages using kcat (formerly known as kafkacat) or by exec into the running container like this:
source ./scripts/check_docker_podman.sh
KAFKA_CONTAINER_NAME=$(${DOCKER} ps | grep inventory-api-kafka | awk '{print $1}')
${DOCKER} exec -i -t ${KAFKA_CONTAINER_NAME} /bin/bash
# Once in the container
./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic kessel-inventoryManually terminate Kessel inventory and then run the following to stop kafka:
make inventory-down-kafkaSimilar as above, but instead of running Kafka, this will configure inventory to use a Keycloak service for authentication.
- Sets up a keycloak instance running at port 8084 with myrealm config file.
- Set up a default service account with clientId:
test-svc. Refer to get-token to learn how to fetch a token. - Refer to sso-inventory-api.yaml for additional configuration
As before you'll need to run the Relations Compose steps available in the Relations API repo
To start use:
make inventory-up-ssoOnce it has started, you will need to fetch a token and use it when making calls to the service.
To get a token use:
make get-tokenYou can then export an ENV with that value and use in calls such as:
curl -H "Authorization: bearer ${TOKEN}" # ...To stop use:
make inventory-down-ssoInstructions to deploy Kessel Inventory in an ephemeral cluster can be found on Kessel docs
Once there is any change in the proto files (under (/api/kessel)[./api/kessel]) an update is required.
This command will generate code and an (openapi)[./openapi.yaml] file from the proto files.
make apiWe can run the following command to update if there are expected breaking changes.
make api_breakingBy default, the quay repository is quay.io/cloudservices/kessel-inventory. If you wish to use another for testing, set IMAGE value first
export IMAGE=your-quay-repo # if desired
make docker-build-pushThis is an alternative to the above command for macOS users, but should work for any arch
export QUAY_REPO_INVENTORY=your-quay-repo # required
podman login quay.io # required, this target assumes you are already logged in
make build-push-minimalAll these examples use the REST API and assume we are running the default local version adjustments needs to be made to the curl requests if running with different configuration, such as port, authentication mechanisms, etc.
Note: When testing in Stage, the current schema leveraged by Relations only supports notifications integrations and not any of the infra we have in our API (RHEL hosts, K8s Clusters, etc). Testing with any other resource type will throw errors from Relations API but will still succeed in Inventory API
The Kessel Inventory includes health check endpoints for readiness and liveness probes.
The readyz endpoint checks if the service is ready to handle requests.
curl http://localhost:8000/api/inventory/v1/readyzThe livez endpoint checks if the service is alive and functioning correctly.
curl http://localhost:8000/api/inventory/v1/livezResources can be added, updated and deleted to our inventory. Right now we support the following resources:
rhel-hostnotifications-integrationk8s-clusterk8s-policy
To add a rhel-host to the inventory:
To hit the REST endpoint use the following curl command
curl -H "Content-Type: application/json" --data "@data/host.json" http://localhost:8000/api/inventory/v1beta1/resources/rhel-hostsTo hit the gRPC endpoint use the following grpcurl command
grpcurl -plaintext -d @ localhost:9000 kessel.inventory.v1beta1.resources.KesselRhelHostService.CreateRhelHost < data/host.json
To update it:
To hit the REST endpoint
curl -XPUT -H "Content-Type: application/json" --data "@data/host.json" http://localhost:8000/api/inventory/v1beta1/resources/rhel-hostsTo hit the gRPC endpoint
grpcurl -plaintext -d @ localhost:9000 kessel.inventory.v1beta1.resources.KesselRhelHostService.UpdateRhelHost < data/host.json
and finally, to delete it, note that we use a different file, as the only required information is the reporter data.
To hit the REST endpoint
curl -XDELETE -H "Content-Type: application/json" --data "@data/host-reporter.json" http://localhost:8000/api/inventory/v1beta1/resources/rhel-hostsTo hit the gRPC endpoint
grpcurl -plaintext -d @ localhost:9000 kessel.inventory.v1beta1.resources.KesselRhelHostService.DeleteRhelHost < data/host-reporter.json
To add a notifications integration (useful for testing in stage)
# create the integration (auth is required for stage -- see internal docs)
curl -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d @data/notifications-integrations.json localhost:8000/api/inventory/v1beta1/resources/notifications-integrations
# delete the integration
curl -X DELETE -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d @data/notifications-integration-reporter.json localhost:8000/api/inventory/v1beta1/resources/notifications-integrations
### Adding a new relationship (k8s-policy is propagated to k8s-cluster)
To add a `k8s-policy_ispropagatedto-k8s-cluster` relationship, first lets add the related resources `k8s-policy` and `k8s-cluster`.
```shell
curl -H "Content-Type: application/json" --data "@data/k8s-cluster.json" http://localhost:8000/api/inventory/v1beta1/resources/k8s-clusters
curl -H "Content-Type: application/json" --data "@data/k8s-policy.json" http://localhost:8000/api/inventory/v1beta1/resources/k8s-policiesAnd then you can create the relation:
curl -H "Content-Type: application/json" --data "@data/k8spolicy_ispropagatedto_k8scluster.json" http://localhost:8000/api/inventory/v1beta1/resource-relationships/k8s-policy_is-propagated-to_k8s-clusterTo update it:
curl -X PUT -H "Content-Type: application/json" --data "@data/k8spolicy_ispropagatedto_k8scluster.json" http://localhost:8000/api/inventory/v1beta1/resource-relationships/k8s-policy_is-propagated-to_k8s-clusterAnd finally, to delete it, notice that the data file is different this time. We only need the reporter data.
curl -X DELETE -H "Content-Type: application/json" --data "@data/relationship_reporter_data.json" http://localhost:8000/api/inventory/v1beta1/resource-relationships/k8s-policy_is-propagated-to_k8s-clusterThe default development config has this option disabled. You can check Alternatives way of running this service for configurations that have Kessel relations enabled.
Supposing Kessel relations is running in localhost:9000, you can enable it by updating the config as follows:
authz:
impl: kessel
kessel:
insecure-client: true
url: localhost:9000
enable-oidc-auth: falseIf you want to enable OIDC authentication with SSO, you can use this instead:
authz:
impl: kessel
kessel:
insecure-client: true
url: localhost:9000
enable-oidc-auth: true
sa-client-id: "<service-id>"
sa-client-secret: "<secret>"
sso-token-endpoint: "http://localhost:8084/realms/redhat-external/protocol/openid-connect/token"
Tests can be run using:
make testFor end-to-test info see here.
Inventory API is configured to build with FIPS capable libraries and produce FIPS capaable binaries when running on FIPS enabled clusters.
To validate the current running container is FIPS capable:
# exec or rsh into running pod
# Reference the fips_enabled file that ubi9 creates for the host
cat /proc/sys/crypto/fips_enabled
# Expected output:
1
# Check go tool for the binary
go tool nm /usr/local/bin/inventory-api | grep FIPS
# Expected output should reference openssl FIPS settings
# Ensure openssl providers have a FIPS provider active
openssl list -providers | grep -A 3 fips
# Expected output
fips
name: Red Hat Enterprise Linux 9 - OpenSSL FIPS Provider
version: 3.0.7-395c1a240fbfffd8
status: activeFollow the steps below to contribute:
- Fork the project
- Create a new branch for your feature
- Run tests and Pr check
- Submit a pull request