Rebrand: Sentry -> Cairn OBS
Full rebrand across cosmetic branding, code identifiers, and infrastructure/data-plane naming, using the supplied Cairn OBS logo package. Cosmetic: favicon/logo swap (also closes a stale license-audit finding -- the old favicon was SvelteKit's unreplaced scaffold logo), new centered welcome landing page, larger/legible sidebar logo, page titles, CLAUDE.md/README/docs prose. Code identifiers: Go module path github.com/sentry/sentry -> github.com/cairnobs/cairnobs across all 13 modules and ~91 files (protoc regenerated); Rust crates sentry-agent/sentry-parser/sentry-search -> cairnobs-*; CLI sentryctl -> cairnobsctl; Terraform provider fully renamed (sentry_dashboard etc. -> cairnobs_dashboard, provider type, env vars); every session/auth cookie name; agent config paths and Windows service identity. Deliberately preserved: the gRPC wire protocol's protobuf packages (sentry.logs.v1, sentry.agent.v1) and their Go import directory (proto/sentry/...) -- renaming the wire-level package would break every currently-deployed agent binary (confirmed two real hosts, including mail.inbuxa.com, are actively streaming through this exact contract) until rebuilt and redeployed in lockstep with an ingest cutover. Only the Go module path wrapping the generated code changes. Infrastructure: every docker-compose container name (root and three component-level compose files); the Helm chart (directory, Chart.yaml, named-template helpers, all templates, values.yaml image repos); Kubernetes Operator (CRD group sentry.io -> cairnobs.io, both CRD YAML files, Go identifiers, RBAC markers); the coupled enterprise/tenantcrd package. Caught and fixed real path-coupling bugs along the way: the Helm chart's search/ingest volume mounts and the dev-only-credential detection constant vs. docker-compose.yml's literal values had to move together or a security warning would have silently stopped firing. Data plane: Postgres database sentry_metadata -> cairnobs_metadata and role sentry -> cairnobs; ClickHouse database sentry -> cairnobs; Kafka topic sentry.logs.raw -> cairnobs.logs.raw and its consumer groups. Source-level defaults, docker-compose.yml, and every migrate.sh/ provision script default updated together; already-applied migration files left untouched per this repo's immutable-migration convention. Verified at every layer: all 13 Go modules build/vet/test clean, both Rust workspaces (agent, search) build/clippy/test clean, npm run check/ build clean, docker compose config validates on all four compose files. Live-verified against a real docker stack multiple times through this work, including a final fresh-volume run confirming the actual renamed Postgres database/role, ClickHouse database, and Kafka topic all work end to end with a real login and query, zero console errors.
This commit is contained in:
@@ -372,7 +372,7 @@ integration tests are skipped by default and only run with
|
||||
docker run --rm --network sentry_default -v $(pwd)/..:/src -w /src/enterprise \
|
||||
-e AUDIT_TEST_POSTGRES_ADDR=metadata-postgres:5432 \
|
||||
-e AUDIT_TEST_POSTGRES_PASSWORD=audit-writer-dev-only \
|
||||
-e AUDIT_TEST_ADMIN_PASSWORD=sentry-dev-only \
|
||||
-e AUDIT_TEST_ADMIN_PASSWORD=cairnobs-dev-only \
|
||||
golang:1.25-alpine go test ./internal/audit/... -v
|
||||
```
|
||||
|
||||
@@ -382,7 +382,7 @@ constraints), skipped unless `RBACSTORE_TEST_POSTGRES_ADDR` is set:
|
||||
```sh
|
||||
docker run --rm --network sentry_default -v $(pwd)/..:/src -w /src/enterprise \
|
||||
-e RBACSTORE_TEST_POSTGRES_ADDR=metadata-postgres:5432 \
|
||||
-e RBACSTORE_TEST_POSTGRES_PASSWORD=sentry-dev-only \
|
||||
-e RBACSTORE_TEST_POSTGRES_PASSWORD=cairnobs-dev-only \
|
||||
golang:1.25-alpine go test ./internal/rbacstore/... -v
|
||||
```
|
||||
|
||||
@@ -394,12 +394,12 @@ via `go.mod`'s `replace` directives to `../api`):
|
||||
```sh
|
||||
docker run --rm --network sentry_default -v $(pwd)/..:/src -w /src/enterprise \
|
||||
-e TENANTPROVISION_TEST_CLICKHOUSE_ADDR=clickhouse:9000 \
|
||||
-e TENANTPROVISION_TEST_CLICKHOUSE_PASSWORD=sentry-dev-only \
|
||||
-e TENANTPROVISION_TEST_CLICKHOUSE_PASSWORD=cairnobs-dev-only \
|
||||
golang:1.25-alpine go test ./internal/tenantprovision/... -v
|
||||
|
||||
docker run --rm --network sentry_default -v $(pwd)/..:/src -w /src/enterprise \
|
||||
-e CHRUNNER_TEST_CLICKHOUSE_ADDR=clickhouse:9000 \
|
||||
-e CHRUNNER_TEST_CLICKHOUSE_PASSWORD=sentry-dev-only \
|
||||
-e CHRUNNER_TEST_CLICKHOUSE_PASSWORD=cairnobs-dev-only \
|
||||
golang:1.25-alpine go test ./internal/chrunner/... -v
|
||||
```
|
||||
|
||||
|
||||
@@ -42,23 +42,23 @@ import (
|
||||
chdriver "github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"github.com/sentry/sentry/api/agents"
|
||||
"github.com/sentry/sentry/api/ai/aiapi"
|
||||
"github.com/sentry/sentry/api/ai/provider/ollama"
|
||||
"github.com/sentry/sentry/api/ai/router"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/dashboards"
|
||||
"github.com/sentry/sentry/api/httpserver"
|
||||
"github.com/sentry/sentry/api/queryapi"
|
||||
"github.com/cairnobs/cairnobs/api/agents"
|
||||
"github.com/cairnobs/cairnobs/api/ai/aiapi"
|
||||
"github.com/cairnobs/cairnobs/api/ai/provider/ollama"
|
||||
"github.com/cairnobs/cairnobs/api/ai/router"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/dashboards"
|
||||
"github.com/cairnobs/cairnobs/api/httpserver"
|
||||
"github.com/cairnobs/cairnobs/api/queryapi"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/apiconfig"
|
||||
"github.com/sentry/sentry/enterprise/internal/audit"
|
||||
"github.com/sentry/sentry/enterprise/internal/chrunner"
|
||||
"github.com/sentry/sentry/enterprise/internal/groundingregistry"
|
||||
"github.com/sentry/sentry/enterprise/internal/rbacstore"
|
||||
"github.com/sentry/sentry/enterprise/internal/searchclient"
|
||||
"github.com/sentry/sentry/enterprise/internal/tenantcrd"
|
||||
"github.com/sentry/sentry/enterprise/internal/tenantprovision"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/apiconfig"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/audit"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/chrunner"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/groundingregistry"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/rbacstore"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/searchclient"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/tenantcrd"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/tenantprovision"
|
||||
)
|
||||
|
||||
// groundingRefreshInterval matches api/cmd/api's own constant of the
|
||||
@@ -295,7 +295,7 @@ func runProvisionTenant(ctx context.Context, logger *slog.Logger, cfg apiconfig.
|
||||
logger.Error("tenant is active but has no data source row -- inconsistent state, refusing", "tenant_id", tenantID)
|
||||
return 1
|
||||
}
|
||||
dataSource, err = rbac.CreateDataSource(ctx, tenantID, "default", tenantID, "/var/lib/sentry-search/tenants/"+tenantID)
|
||||
dataSource, err = rbac.CreateDataSource(ctx, tenantID, "default", tenantID, "/var/lib/cairnobs-search/tenants/"+tenantID)
|
||||
if err != nil {
|
||||
logger.Error("creating data source", "error", err)
|
||||
return 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Command enterprise-auth is Sentry's SSO/tenant-provisioning/RBAC
|
||||
// Command enterprise-auth is Cairn OBS's SSO/tenant-provisioning/RBAC
|
||||
// service (AGPLv3, same as core -- see
|
||||
// /docs/compliance/license-audit-report.md) -- see
|
||||
// /docs/phase-4-isolation-design.md and /docs/phase-4-rbac-design.md.
|
||||
@@ -38,14 +38,14 @@ import (
|
||||
"github.com/crewjam/saml/samlsp"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"github.com/sentry/sentry/api/httpserver"
|
||||
"github.com/sentry/sentry/enterprise/internal/authhandler"
|
||||
"github.com/sentry/sentry/enterprise/internal/config"
|
||||
"github.com/sentry/sentry/enterprise/internal/loginhandler"
|
||||
"github.com/sentry/sentry/enterprise/internal/oidc"
|
||||
"github.com/sentry/sentry/enterprise/internal/rbacstore"
|
||||
samlpkg "github.com/sentry/sentry/enterprise/internal/saml"
|
||||
"github.com/sentry/sentry/enterprise/internal/session"
|
||||
"github.com/cairnobs/cairnobs/api/httpserver"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/authhandler"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/config"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/loginhandler"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/oidc"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/rbacstore"
|
||||
samlpkg "github.com/cairnobs/cairnobs/enterprise/internal/saml"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/session"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -39,10 +39,10 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/chwriter"
|
||||
"github.com/sentry/sentry/enterprise/internal/ingestconfig"
|
||||
"github.com/sentry/sentry/enterprise/internal/rbacstore"
|
||||
"github.com/sentry/sentry/ingest/consumer"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/chwriter"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/ingestconfig"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/rbacstore"
|
||||
"github.com/cairnobs/cairnobs/ingest/consumer"
|
||||
)
|
||||
|
||||
// dataSourceRefreshInterval matches search/src/tenants.rs's
|
||||
|
||||
+8
-8
@@ -1,4 +1,4 @@
|
||||
module github.com/sentry/sentry/enterprise
|
||||
module github.com/cairnobs/cairnobs/enterprise
|
||||
|
||||
go 1.25.0
|
||||
|
||||
@@ -7,24 +7,24 @@ go 1.25.0
|
||||
// enterprise/internal/chrunner's doc comment: it implements api's
|
||||
// executor.SQLRunner interface, which structurally requires importing
|
||||
// the package that defines it.
|
||||
replace github.com/sentry/sentry/api => ../api
|
||||
replace github.com/cairnobs/cairnobs/api => ../api
|
||||
|
||||
// Same allowed direction, against ingest/ instead -- enterprise/internal/
|
||||
// chwriter implements ingest/consumer's chWriter interface, which
|
||||
// structurally requires importing the package that defines it (see
|
||||
// that package's doc comment).
|
||||
replace github.com/sentry/sentry/ingest => ../ingest
|
||||
replace github.com/cairnobs/cairnobs/ingest => ../ingest
|
||||
|
||||
// api's own go.mod replace directive for proto/ is module-local and
|
||||
// doesn't propagate here -- enterprise/ needs its own, or `go build`
|
||||
// tries to fetch github.com/sentry/sentry/proto from a real (nonexistent)
|
||||
// tries to fetch github.com/cairnobs/cairnobs/proto from a real (nonexistent)
|
||||
// remote, since api/searchclient (now transitively imported) depends on
|
||||
// the generated search gRPC stubs.
|
||||
replace github.com/sentry/sentry/proto => ../proto
|
||||
replace github.com/cairnobs/cairnobs/proto => ../proto
|
||||
|
||||
require (
|
||||
github.com/sentry/sentry/api v0.0.0-00010101000000-000000000000
|
||||
github.com/sentry/sentry/ingest v0.0.0-00010101000000-000000000000
|
||||
github.com/cairnobs/cairnobs/api v0.0.0-00010101000000-000000000000
|
||||
github.com/cairnobs/cairnobs/ingest v0.0.0-00010101000000-000000000000
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -34,7 +34,7 @@ require (
|
||||
github.com/go-jose/go-jose/v4 v4.1.4
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.10.0
|
||||
github.com/sentry/sentry/proto v0.0.0-00010101000000-000000000000
|
||||
github.com/cairnobs/cairnobs/proto v0.0.0-00010101000000-000000000000
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/sync v0.22.0
|
||||
google.golang.org/grpc v1.83.0
|
||||
|
||||
@@ -92,7 +92,7 @@ type AuditWriterConfig struct {
|
||||
// DevCredentialWarnings for the full reasoning (duplicated here per
|
||||
// this repo's no-shared-code-between-services convention).
|
||||
const (
|
||||
devOnlyCredential = "sentry-dev-only"
|
||||
devOnlyCredential = "cairnobs-dev-only"
|
||||
devOnlyAuditWriterCredential = "audit-writer-dev-only"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/sentry/sentry/api/agents"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/agents"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
)
|
||||
|
||||
// AgentCommandLogger implements agents.CommandLogger by translating its
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/sentry/sentry/api/ai/aiapi"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/ai/aiapi"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
)
|
||||
|
||||
// AIInteractionLogger implements aiapi.InteractionLogger by translating
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// docker run --rm --network sentry_default -v $(pwd)/../../..:/src -w /src/enterprise \
|
||||
// -e AUDIT_TEST_POSTGRES_ADDR=metadata-postgres:5432 \
|
||||
// -e AUDIT_TEST_POSTGRES_PASSWORD=audit-writer-dev-only \
|
||||
// -e AUDIT_TEST_ADMIN_PASSWORD=sentry-dev-only \
|
||||
// -e AUDIT_TEST_ADMIN_PASSWORD=cairnobs-dev-only \
|
||||
// golang:1.25-alpine go test ./internal/audit/... -v
|
||||
package audit
|
||||
|
||||
@@ -23,9 +23,9 @@ import (
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"github.com/sentry/sentry/api/ai/aiapi"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/queryapi"
|
||||
"github.com/cairnobs/cairnobs/api/ai/aiapi"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/queryapi"
|
||||
)
|
||||
|
||||
func testPool(t *testing.T, user, password string) *pgxpool.Pool {
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/queryapi"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/queryapi"
|
||||
)
|
||||
|
||||
// QueryAPILogger implements queryapi.AuditLogger by translating its
|
||||
|
||||
@@ -25,12 +25,12 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/session"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/session"
|
||||
)
|
||||
|
||||
// SessionCookieName matches the name api/authz.HTTPAuthorizer's
|
||||
// tests and doc comments already assume ("sentry_session").
|
||||
const SessionCookieName = "sentry_session"
|
||||
// tests and doc comments already assume ("cairnobs_session").
|
||||
const SessionCookieName = "cairnobs_session"
|
||||
|
||||
// Features reports which SSO mechanisms are configured -- the response
|
||||
// shape /docs/phase-4-rbac-design.md's "Web UI boundary" section commits
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/session"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/session"
|
||||
)
|
||||
|
||||
// fakeIngestCredentialValidator is an in-memory stand-in for
|
||||
|
||||
@@ -29,8 +29,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/querylang/executor"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/querylang/executor"
|
||||
)
|
||||
|
||||
// DataSource is the minimal shape Registry needs to open one tenant's
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//
|
||||
// docker run --rm --network sentry_default -v $(pwd)/../../..:/src -w /src/enterprise \
|
||||
// -e CHRUNNER_TEST_CLICKHOUSE_ADDR=clickhouse:9000 \
|
||||
// -e CHRUNNER_TEST_CLICKHOUSE_PASSWORD=sentry-dev-only \
|
||||
// -e CHRUNNER_TEST_CLICKHOUSE_PASSWORD=cairnobs-dev-only \
|
||||
// golang:1.25-alpine go test ./internal/chrunner/... -v
|
||||
package chrunner
|
||||
|
||||
@@ -25,9 +25,9 @@ import (
|
||||
|
||||
chdriver "github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/tenantprovision"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/tenantprovision"
|
||||
)
|
||||
|
||||
func testAddr(t *testing.T) string {
|
||||
|
||||
@@ -28,9 +28,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sentry/sentry/ingest/clickhousewriter"
|
||||
"github.com/sentry/sentry/ingest/consumer"
|
||||
logsv1 "github.com/sentry/sentry/proto/sentry/logs/v1"
|
||||
"github.com/cairnobs/cairnobs/ingest/clickhousewriter"
|
||||
"github.com/cairnobs/cairnobs/ingest/consumer"
|
||||
logsv1 "github.com/cairnobs/cairnobs/proto/sentry/logs/v1"
|
||||
)
|
||||
|
||||
// DataSource mirrors chrunner.DataSource -- deliberately not
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// docker run --rm --network sentry_default -v $(pwd)/../../..:/src -w /src/enterprise \
|
||||
// -e CHWRITER_TEST_CLICKHOUSE_ADDR=clickhouse:9000 \
|
||||
// -e CHWRITER_TEST_CLICKHOUSE_PASSWORD=sentry-dev-only \
|
||||
// -e CHWRITER_TEST_CLICKHOUSE_PASSWORD=cairnobs-dev-only \
|
||||
// golang:1.25-alpine go test ./internal/chwriter/... -v
|
||||
package chwriter
|
||||
|
||||
@@ -24,10 +24,10 @@ import (
|
||||
chdriver "github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/tenantprovision"
|
||||
"github.com/sentry/sentry/ingest/clickhousewriter"
|
||||
"github.com/sentry/sentry/ingest/consumer"
|
||||
logsv1 "github.com/sentry/sentry/proto/sentry/logs/v1"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/tenantprovision"
|
||||
"github.com/cairnobs/cairnobs/ingest/clickhousewriter"
|
||||
"github.com/cairnobs/cairnobs/ingest/consumer"
|
||||
logsv1 "github.com/cairnobs/cairnobs/proto/sentry/logs/v1"
|
||||
)
|
||||
|
||||
func discardLogger() *slog.Logger {
|
||||
|
||||
@@ -47,8 +47,8 @@ type Config struct {
|
||||
// in the enterprise deployment," since compromising it lets an attacker
|
||||
// forge any identity, including the RoleService credential.
|
||||
const (
|
||||
devOnlyCredential = "sentry-dev-only"
|
||||
devOnlySigningKey = "sentry-dev-only-session-signing-key-32bytes+"
|
||||
devOnlyCredential = "cairnobs-dev-only"
|
||||
devOnlySigningKey = "cairnobs-dev-only-session-signing-key-32bytes+"
|
||||
)
|
||||
|
||||
// DevCredentialWarnings reports which configured secrets still equal
|
||||
|
||||
@@ -26,10 +26,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sentry/sentry/api/ai/grounding"
|
||||
"github.com/sentry/sentry/api/ai/provider"
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/querylang/executor"
|
||||
"github.com/cairnobs/cairnobs/api/ai/grounding"
|
||||
"github.com/cairnobs/cairnobs/api/ai/provider"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/querylang/executor"
|
||||
)
|
||||
|
||||
// TenantLister returns the currently-active tenant IDs to sample --
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/querylang/executor"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/querylang/executor"
|
||||
)
|
||||
|
||||
// tenantAwareFakeRunner returns a service list keyed by the tenant
|
||||
|
||||
@@ -54,7 +54,7 @@ type BatchConfig struct {
|
||||
// api/internal/config.Config.DevCredentialWarnings for the full
|
||||
// reasoning (duplicated here per this repo's no-shared-code-between-
|
||||
// services convention).
|
||||
const devOnlyCredential = "sentry-dev-only"
|
||||
const devOnlyCredential = "cairnobs-dev-only"
|
||||
|
||||
// DevCredentialWarnings reports whether the configured Postgres
|
||||
// credential still equals the literal dev-only default --
|
||||
|
||||
@@ -32,11 +32,11 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/authhandler"
|
||||
"github.com/sentry/sentry/enterprise/internal/oidc"
|
||||
"github.com/sentry/sentry/enterprise/internal/rbacstore"
|
||||
"github.com/sentry/sentry/enterprise/internal/saml"
|
||||
"github.com/sentry/sentry/enterprise/internal/session"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/authhandler"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/oidc"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/rbacstore"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/saml"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/session"
|
||||
)
|
||||
|
||||
// oidcStateCookieName carries OIDC's CSRF-protection state value between
|
||||
@@ -44,19 +44,19 @@ import (
|
||||
// callback-path cookie (the "double-submit cookie" pattern) rather than
|
||||
// server-side state, since this service otherwise has no per-browser
|
||||
// session store to put it in before a session exists.
|
||||
const oidcStateCookieName = "sentry_oidc_state"
|
||||
const oidcStateCookieName = "cairnobs_oidc_state"
|
||||
|
||||
// samlRequestCookieName is SAML's analog -- carries the AuthnRequest ID
|
||||
// LoginURL generated, so the ACS handler can pass it back to
|
||||
// ParseResponse's possibleRequestIDs (SAML's actual replay/unsolicited-
|
||||
// response defense -- see saml.ServiceProvider.LoginURL's doc comment).
|
||||
const samlRequestCookieName = "sentry_saml_request"
|
||||
const samlRequestCookieName = "cairnobs_saml_request"
|
||||
|
||||
// pendingLoginCookieName carries a PendingLoginClaims token from
|
||||
// finishLogin's multi-membership branch through GET /auth/memberships
|
||||
// and POST /auth/select-tenant -- Path "/auth" (not "/") so it's never
|
||||
// sent on ordinary requests, only the two routes that need it.
|
||||
const pendingLoginCookieName = "sentry_pending_login"
|
||||
const pendingLoginCookieName = "cairnobs_pending_login"
|
||||
|
||||
// loginCookieTTL bounds how long a user has to complete the IdP round
|
||||
// trip -- generous enough for a real login form, short enough that a
|
||||
|
||||
@@ -23,12 +23,12 @@ import (
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc/oidctest"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/oidc"
|
||||
"github.com/sentry/sentry/enterprise/internal/rbacstore"
|
||||
"github.com/sentry/sentry/enterprise/internal/session"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/oidc"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/rbacstore"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/session"
|
||||
)
|
||||
|
||||
const testClientID = "sentry-test-client"
|
||||
const testClientID = "cairnobs-test-client"
|
||||
const testKeyID = "test-key-1"
|
||||
|
||||
// fakeUserStore is an in-memory stand-in for *rbacstore.Store, keyed by
|
||||
@@ -128,7 +128,7 @@ func newTestOIDCProvider(t *testing.T, idp *testIdP) *oidc.Provider {
|
||||
t.Helper()
|
||||
p, err := oidc.New(context.Background(), oidc.Config{
|
||||
IssuerURL: idp.srv.URL, ClientID: testClientID, ClientSecret: "secret",
|
||||
RedirectURL: "http://sentry-test/auth/oidc/callback",
|
||||
RedirectURL: "http://cairnobs-test/auth/oidc/callback",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("oidc.New: %v", err)
|
||||
@@ -221,12 +221,12 @@ func TestFullLoginFlowIssuesSessionForSingleMembership(t *testing.T) {
|
||||
|
||||
var sessionCookie *http.Cookie
|
||||
for _, c := range rec.Result().Cookies() {
|
||||
if c.Name == "sentry_session" {
|
||||
if c.Name == "cairnobs_session" {
|
||||
sessionCookie = c
|
||||
}
|
||||
}
|
||||
if sessionCookie == nil || sessionCookie.Value == "" {
|
||||
t.Fatal("expected a sentry_session cookie to be set")
|
||||
t.Fatal("expected a cairnobs_session cookie to be set")
|
||||
}
|
||||
claims, err := sessionManager.Validate(sessionCookie.Value)
|
||||
if err != nil {
|
||||
@@ -278,7 +278,7 @@ func TestFullLoginFlowStartsTenantSelectionForMultipleMemberships(t *testing.T)
|
||||
switch c.Name {
|
||||
case pendingLoginCookieName:
|
||||
pendingCookie = c
|
||||
case "sentry_session":
|
||||
case "cairnobs_session":
|
||||
sessionCookie = c
|
||||
}
|
||||
}
|
||||
@@ -408,14 +408,14 @@ func TestSelectTenantIssuesSessionForChosenTenant(t *testing.T) {
|
||||
var sessionCookie, clearedPendingCookie *http.Cookie
|
||||
for _, c := range rec.Result().Cookies() {
|
||||
switch c.Name {
|
||||
case "sentry_session":
|
||||
case "cairnobs_session":
|
||||
sessionCookie = c
|
||||
case pendingLoginCookieName:
|
||||
clearedPendingCookie = c
|
||||
}
|
||||
}
|
||||
if sessionCookie == nil || sessionCookie.Value == "" {
|
||||
t.Fatal("expected a sentry_session cookie to be set")
|
||||
t.Fatal("expected a cairnobs_session cookie to be set")
|
||||
}
|
||||
if clearedPendingCookie == nil || clearedPendingCookie.MaxAge >= 0 {
|
||||
t.Fatalf("expected the pending-login cookie to be cleared (MaxAge < 0), got %+v", clearedPendingCookie)
|
||||
@@ -458,7 +458,7 @@ func TestSelectTenantRejectsTenantOutsideMembership(t *testing.T) {
|
||||
t.Fatalf("status = %d, want 403; body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
for _, c := range rec.Result().Cookies() {
|
||||
if c.Name == "sentry_session" {
|
||||
if c.Name == "cairnobs_session" {
|
||||
t.Fatal("must not issue a session cookie for a tenant outside the identity's memberships")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ import (
|
||||
"github.com/crewjam/saml"
|
||||
"github.com/crewjam/saml/samlidp"
|
||||
|
||||
"github.com/sentry/sentry/enterprise/internal/rbacstore"
|
||||
samlpkg "github.com/sentry/sentry/enterprise/internal/saml"
|
||||
"github.com/cairnobs/cairnobs/enterprise/internal/rbacstore"
|
||||
samlpkg "github.com/cairnobs/cairnobs/enterprise/internal/saml"
|
||||
)
|
||||
|
||||
const (
|
||||
testSAMLEntityID = "https://sentry-test.example.com/saml/metadata"
|
||||
testSAMLACSURL = "https://sentry-test.example.com/auth/saml/acs"
|
||||
testSAMLEntityID = "https://cairnobs-test.example.com/saml/metadata"
|
||||
testSAMLACSURL = "https://cairnobs-test.example.com/auth/saml/acs"
|
||||
)
|
||||
|
||||
// testSAMLIdP bundles a real samlidp.Server with the SP key/cert it was
|
||||
@@ -79,14 +79,14 @@ func genSelfSignedCert(t *testing.T, commonName string) (*rsa.PrivateKey, *x509.
|
||||
return key, cert
|
||||
}
|
||||
|
||||
// newTestSAMLIdP starts a real samlidp.Server and registers Sentry's SP
|
||||
// newTestSAMLIdP starts a real samlidp.Server and registers Cairn OBS's SP
|
||||
// metadata with it directly via the IdP's own PUT /services/{id}
|
||||
// endpoint -- the same mechanism a real IdP admin uses, not a shortcut
|
||||
// that reaches into samlidp's unexported state.
|
||||
func newTestSAMLIdP(t *testing.T) *testSAMLIdP {
|
||||
t.Helper()
|
||||
idpKey, idpCert := genSelfSignedCert(t, "sentry-test-idp")
|
||||
spKey, spCert := genSelfSignedCert(t, "sentry-test-sp")
|
||||
idpKey, idpCert := genSelfSignedCert(t, "cairnobs-test-idp")
|
||||
spKey, spCert := genSelfSignedCert(t, "cairnobs-test-sp")
|
||||
|
||||
store := &samlidp.MemoryStore{}
|
||||
idpServer, err := samlidp.New(samlidp.Options{
|
||||
@@ -122,7 +122,7 @@ func newTestSAMLIdP(t *testing.T) *testSAMLIdP {
|
||||
if err != nil {
|
||||
t.Fatalf("marshaling sp metadata: %v", err)
|
||||
}
|
||||
putReq := httptest.NewRequest(http.MethodPut, "/services/sentry-test-sp", strings.NewReader(string(spMetadataXML)))
|
||||
putReq := httptest.NewRequest(http.MethodPut, "/services/cairnobs-test-sp", strings.NewReader(string(spMetadataXML)))
|
||||
putRec := httptest.NewRecorder()
|
||||
idpServer.ServeHTTP(putRec, putReq)
|
||||
if putRec.Code != http.StatusNoContent {
|
||||
@@ -324,12 +324,12 @@ func TestFullSAMLLoginFlowIssuesSessionForSingleMembership(t *testing.T) {
|
||||
|
||||
var sessionCookie *http.Cookie
|
||||
for _, c := range rec.Result().Cookies() {
|
||||
if c.Name == "sentry_session" {
|
||||
if c.Name == "cairnobs_session" {
|
||||
sessionCookie = c
|
||||
}
|
||||
}
|
||||
if sessionCookie == nil || sessionCookie.Value == "" {
|
||||
t.Fatal("expected a sentry_session cookie to be set")
|
||||
t.Fatal("expected a cairnobs_session cookie to be set")
|
||||
}
|
||||
claims, err := sessionManager.Validate(sessionCookie.Value)
|
||||
if err != nil {
|
||||
@@ -401,7 +401,7 @@ func TestSAMLACSRejectsMissingRequestCookie(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
h.RegisterRoutes(mux)
|
||||
|
||||
// No prior GET /auth/saml/login, so no sentry_saml_request cookie --
|
||||
// No prior GET /auth/saml/login, so no cairnobs_saml_request cookie --
|
||||
// simulates an attacker POSTing a captured/forged response directly
|
||||
// at the ACS endpoint with no matching request state.
|
||||
form := url.Values{"SAMLResponse": {"irrelevant"}, "RelayState": {""}}
|
||||
|
||||
@@ -35,7 +35,7 @@ type Provider struct {
|
||||
oauth2 oauth2.Config
|
||||
}
|
||||
|
||||
// Claims is the subset of ID token claims Sentry actually uses. Extend
|
||||
// Claims is the subset of ID token claims Cairn OBS actually uses. Extend
|
||||
// deliberately, not by passing the raw claim map further up the stack --
|
||||
// every field added here is a field internal/session has to decide how
|
||||
// to trust.
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestNewDiscoversRealIssuer(t *testing.T) {
|
||||
})
|
||||
|
||||
p, err := New(context.Background(), Config{
|
||||
IssuerURL: srv.URL, ClientID: "sentry", ClientSecret: "secret", RedirectURL: "http://localhost/callback",
|
||||
IssuerURL: srv.URL, ClientID: "cairnobs", ClientSecret: "secret", RedirectURL: "http://localhost/callback",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/sentry/sentry/api/dashboards"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/dashboards"
|
||||
)
|
||||
|
||||
// DashboardPermissions implements dashboards.PermissionStore by
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
// docker run --rm --network sentry_default -v $(pwd)/../../..:/src -w /src/enterprise \
|
||||
// -e RBACSTORE_TEST_POSTGRES_ADDR=metadata-postgres:5432 \
|
||||
// -e RBACSTORE_TEST_POSTGRES_PASSWORD=sentry-dev-only \
|
||||
// -e RBACSTORE_TEST_POSTGRES_PASSWORD=cairnobs-dev-only \
|
||||
// golang:1.25-alpine go test ./internal/rbacstore/... -v
|
||||
package rbacstore
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
)
|
||||
|
||||
func testStore(t *testing.T) *Store {
|
||||
@@ -337,7 +337,7 @@ func TestCreateDataSourceThenSetCredentials(t *testing.T) {
|
||||
t.Fatalf("CreateTenant: %v", err)
|
||||
}
|
||||
|
||||
ds, err := s.CreateDataSource(ctx, tenantID, "default", tenantID, "/var/lib/sentry-search/tenants/"+tenantID)
|
||||
ds, err := s.CreateDataSource(ctx, tenantID, "default", tenantID, "/var/lib/cairnobs-search/tenants/"+tenantID)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDataSource: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Package saml wires crewjam/saml into a small SP (service provider)
|
||||
// client: build the login redirect, and validate/parse an incoming
|
||||
// assertion. Deliberately not using crewjam's samlsp.Middleware, which
|
||||
// owns its own session/cookie handling -- Sentry's session concept lives
|
||||
// owns its own session/cookie handling -- Cairn OBS's session concept lives
|
||||
// in internal/session, one layer up, so this package only does the SAML
|
||||
// protocol mechanics (XML signing/parsing), per the explicit instruction
|
||||
// not to hand-roll that crypto.
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
// EntityID identifies Sentry to the IdP, conventionally Sentry's own
|
||||
// EntityID identifies Cairn OBS to the IdP, conventionally Cairn OBS's own
|
||||
// metadata URL.
|
||||
EntityID string
|
||||
// ACSURL is where the IdP redirects the browser back to with the
|
||||
@@ -109,7 +109,7 @@ func (s *ServiceProvider) LoginURL(relayState string) (redirectURL, requestID st
|
||||
return redirect.String(), req.ID, nil
|
||||
}
|
||||
|
||||
// Claims is the subset of an assertion Sentry uses -- same "extend
|
||||
// Claims is the subset of an assertion Cairn OBS uses -- same "extend
|
||||
// deliberately" reasoning as oidc.Claims.
|
||||
type Claims struct {
|
||||
NameID string
|
||||
@@ -117,7 +117,7 @@ type Claims struct {
|
||||
}
|
||||
|
||||
// ParseResponse validates an incoming SAML response (signature, issuer,
|
||||
// audience, timing) and extracts the fields Sentry cares about. This is
|
||||
// audience, timing) and extracts the fields Cairn OBS cares about. This is
|
||||
// the step that actually establishes trust -- crewjam/saml's
|
||||
// ParseResponse does the XML signature verification, not this package.
|
||||
func (s *ServiceProvider) ParseResponse(r *http.Request, possibleRequestIDs []string) (*Claims, error) {
|
||||
@@ -186,7 +186,7 @@ func selfSignedCert() (*tls.Certificate, error) {
|
||||
}
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{CommonName: "sentry-saml-sp-dev"},
|
||||
Subject: pkix.Name{CommonName: "cairnobs-saml-sp-dev"},
|
||||
NotBefore: time.Now().Add(-time.Hour),
|
||||
NotAfter: time.Now().Add(24 * time.Hour * 365),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||
|
||||
@@ -41,8 +41,8 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
searchv1 "github.com/sentry/sentry/proto/sentry/search/v1"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
searchv1 "github.com/cairnobs/cairnobs/proto/sentry/search/v1"
|
||||
)
|
||||
|
||||
// TenantChecker answers "is this tenant allowed to search at all" --
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/sentry/sentry/api/authz"
|
||||
searchv1 "github.com/sentry/sentry/proto/sentry/search/v1"
|
||||
"github.com/cairnobs/cairnobs/api/authz"
|
||||
searchv1 "github.com/cairnobs/cairnobs/proto/sentry/search/v1"
|
||||
)
|
||||
|
||||
type fakeSearchServer struct {
|
||||
|
||||
@@ -38,10 +38,10 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// tenantGVR identifies deploy/operator/config/crd/sentry.io_tenants.yaml's
|
||||
// tenantGVR identifies deploy/operator/config/crd/cairnobs.io_tenants.yaml's
|
||||
// resource -- kept as a plain schema.GroupVersionResource (not the typed
|
||||
// package) for the reason this file's doc comment explains.
|
||||
var tenantGVR = schema.GroupVersionResource{Group: "sentry.io", Version: "v1alpha1", Resource: "tenants"}
|
||||
var tenantGVR = schema.GroupVersionResource{Group: "cairnobs.io", Version: "v1alpha1", Resource: "tenants"}
|
||||
|
||||
// Syncer talks to the K8s API. Construction (New) is the only place
|
||||
// that can fail for "no cluster reachable" reasons -- Sync itself
|
||||
@@ -105,7 +105,7 @@ type Credentials struct {
|
||||
// runProvisionTenant) finds and updates the same Secret rather than
|
||||
// creating a second one.
|
||||
func SecretName(tenantID string) string {
|
||||
return fmt.Sprintf("sentry-tenant-%s-clickhouse", tenantID)
|
||||
return fmt.Sprintf("cairnobs-tenant-%s-clickhouse", tenantID)
|
||||
}
|
||||
|
||||
// Sync upserts the Tenant object (creating it with spec.displayName if
|
||||
@@ -145,7 +145,7 @@ func (s *Syncer) upsertTenant(ctx context.Context, tenantID, displayName string)
|
||||
}
|
||||
|
||||
obj := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"apiVersion": "sentry.io/v1alpha1",
|
||||
"apiVersion": "cairnobs.io/v1alpha1",
|
||||
"kind": "Tenant",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": tenantID,
|
||||
@@ -170,8 +170,8 @@ func (s *Syncer) upsertSecret(ctx context.Context, tenantID, secretName string,
|
||||
Name: secretName,
|
||||
Namespace: s.namespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/managed-by": "sentry-enterprise-api",
|
||||
"sentry.io/tenant": tenantID,
|
||||
"app.kubernetes.io/managed-by": "cairnobs-enterprise-api",
|
||||
"cairnobs.io/tenant": tenantID,
|
||||
},
|
||||
// Owned by the Tenant object even though a different
|
||||
// process (this one, not the operator's controller)
|
||||
@@ -179,7 +179,7 @@ func (s *Syncer) upsertSecret(ctx context.Context, tenantID, secretName string,
|
||||
// OwnerReferences regardless of which actor set them, so
|
||||
// deleting the Tenant still cleans this Secret up.
|
||||
OwnerReferences: []metav1.OwnerReference{{
|
||||
APIVersion: "sentry.io/v1alpha1",
|
||||
APIVersion: "cairnobs.io/v1alpha1",
|
||||
Kind: "Tenant",
|
||||
Name: tenantID,
|
||||
UID: tenantUID,
|
||||
|
||||
@@ -39,8 +39,8 @@ func getTenant(t *testing.T, s *Syncer, tenantID string) *unstructured.Unstructu
|
||||
}
|
||||
|
||||
func TestSyncCreatesTenantObjectWithDisplayName(t *testing.T) {
|
||||
s := newTestSyncer(t, "sentry")
|
||||
err := s.Sync(context.Background(), "acme", "Acme Corp", "/var/lib/sentry-search/tenants/acme", Credentials{Username: "tenant_acme", Password: "secret-pw"})
|
||||
s := newTestSyncer(t, "cairnobs")
|
||||
err := s.Sync(context.Background(), "acme", "Acme Corp", "/var/lib/cairnobs-search/tenants/acme", Credentials{Username: "tenant_acme", Password: "secret-pw"})
|
||||
if err != nil {
|
||||
t.Fatalf("Sync: %v", err)
|
||||
}
|
||||
@@ -53,8 +53,8 @@ func TestSyncCreatesTenantObjectWithDisplayName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSyncSetsRealStatusFields(t *testing.T) {
|
||||
s := newTestSyncer(t, "sentry")
|
||||
err := s.Sync(context.Background(), "acme", "Acme Corp", "/var/lib/sentry-search/tenants/acme", Credentials{Username: "tenant_acme", Password: "secret-pw"})
|
||||
s := newTestSyncer(t, "cairnobs")
|
||||
err := s.Sync(context.Background(), "acme", "Acme Corp", "/var/lib/cairnobs-search/tenants/acme", Credentials{Username: "tenant_acme", Password: "secret-pw"})
|
||||
if err != nil {
|
||||
t.Fatalf("Sync: %v", err)
|
||||
}
|
||||
@@ -65,23 +65,23 @@ func TestSyncSetsRealStatusFields(t *testing.T) {
|
||||
t.Fatalf("status.clickHouseDatabaseName = %q, want acme", dbName)
|
||||
}
|
||||
secretRef, _, _ := unstructured.NestedString(obj.Object, "status", "clickHouseSecretRef")
|
||||
if secretRef != "sentry-tenant-acme-clickhouse" {
|
||||
t.Fatalf("status.clickHouseSecretRef = %q, want sentry-tenant-acme-clickhouse", secretRef)
|
||||
if secretRef != "cairnobs-tenant-acme-clickhouse" {
|
||||
t.Fatalf("status.clickHouseSecretRef = %q, want cairnobs-tenant-acme-clickhouse", secretRef)
|
||||
}
|
||||
indexPath, _, _ := unstructured.NestedString(obj.Object, "status", "tantivyIndexPath")
|
||||
if indexPath != "/var/lib/sentry-search/tenants/acme" {
|
||||
t.Fatalf("status.tantivyIndexPath = %q, want /var/lib/sentry-search/tenants/acme", indexPath)
|
||||
if indexPath != "/var/lib/cairnobs-search/tenants/acme" {
|
||||
t.Fatalf("status.tantivyIndexPath = %q, want /var/lib/cairnobs-search/tenants/acme", indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncCreatesSecretOwnedByTenant(t *testing.T) {
|
||||
s := newTestSyncer(t, "sentry")
|
||||
s := newTestSyncer(t, "cairnobs")
|
||||
err := s.Sync(context.Background(), "acme", "Acme Corp", "/idx", Credentials{Username: "tenant_acme", Password: "secret-pw"})
|
||||
if err != nil {
|
||||
t.Fatalf("Sync: %v", err)
|
||||
}
|
||||
|
||||
secret, err := s.clientset.CoreV1().Secrets("sentry").Get(context.Background(), "sentry-tenant-acme-clickhouse", metav1.GetOptions{})
|
||||
secret, err := s.clientset.CoreV1().Secrets("cairnobs").Get(context.Background(), "cairnobs-tenant-acme-clickhouse", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("getting secret: %v", err)
|
||||
}
|
||||
@@ -100,7 +100,7 @@ func TestSyncCreatesSecretOwnedByTenant(t *testing.T) {
|
||||
// Tenant object, must not error, and must never silently swap in
|
||||
// different credentials than what was passed.
|
||||
func TestSyncIsIdempotentAndNeverChangesCredentials(t *testing.T) {
|
||||
s := newTestSyncer(t, "sentry")
|
||||
s := newTestSyncer(t, "cairnobs")
|
||||
ctx := context.Background()
|
||||
creds := Credentials{Username: "tenant_acme", Password: "secret-pw"}
|
||||
|
||||
@@ -111,7 +111,7 @@ func TestSyncIsIdempotentAndNeverChangesCredentials(t *testing.T) {
|
||||
t.Fatalf("second Sync: %v", err)
|
||||
}
|
||||
|
||||
list, err := s.dynamic.Resource(tenantGVR).Namespace("sentry").List(ctx, metav1.ListOptions{})
|
||||
list, err := s.dynamic.Resource(tenantGVR).Namespace("cairnobs").List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("listing tenants: %v", err)
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func TestSyncIsIdempotentAndNeverChangesCredentials(t *testing.T) {
|
||||
t.Fatalf("expected exactly one Tenant object after two Syncs, got %d", len(list.Items))
|
||||
}
|
||||
|
||||
secret, err := s.clientset.CoreV1().Secrets("sentry").Get(ctx, "sentry-tenant-acme-clickhouse", metav1.GetOptions{})
|
||||
secret, err := s.clientset.CoreV1().Secrets("cairnobs").Get(ctx, "cairnobs-tenant-acme-clickhouse", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("getting secret: %v", err)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func TestSyncIsIdempotentAndNeverChangesCredentials(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSyncPreservesExistingTenantObjectDisplayName(t *testing.T) {
|
||||
s := newTestSyncer(t, "sentry")
|
||||
s := newTestSyncer(t, "cairnobs")
|
||||
ctx := context.Background()
|
||||
|
||||
// A human/GitOps process already created this Tenant object (e.g.
|
||||
@@ -137,12 +137,12 @@ func TestSyncPreservesExistingTenantObjectDisplayName(t *testing.T) {
|
||||
// -provision-tenant ever ran -- Sync must not overwrite their
|
||||
// chosen displayName with its own.
|
||||
pre := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"apiVersion": "sentry.io/v1alpha1",
|
||||
"apiVersion": "cairnobs.io/v1alpha1",
|
||||
"kind": "Tenant",
|
||||
"metadata": map[string]interface{}{"name": "acme", "namespace": "sentry"},
|
||||
"metadata": map[string]interface{}{"name": "acme", "namespace": "cairnobs"},
|
||||
"spec": map[string]interface{}{"displayName": "Human-Chosen Name"},
|
||||
}}
|
||||
if _, err := s.dynamic.Resource(tenantGVR).Namespace("sentry").Create(ctx, pre, metav1.CreateOptions{}); err != nil {
|
||||
if _, err := s.dynamic.Resource(tenantGVR).Namespace("cairnobs").Create(ctx, pre, metav1.CreateOptions{}); err != nil {
|
||||
t.Fatalf("pre-creating tenant: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// docker run --rm --network sentry_default -v $(pwd)/../../..:/src -w /src/enterprise \
|
||||
// -e TENANTPROVISION_TEST_CLICKHOUSE_ADDR=clickhouse:9000 \
|
||||
// -e TENANTPROVISION_TEST_CLICKHOUSE_PASSWORD=sentry-dev-only \
|
||||
// -e TENANTPROVISION_TEST_CLICKHOUSE_PASSWORD=cairnobs-dev-only \
|
||||
// golang:1.25-alpine go test ./internal/tenantprovision/... -v
|
||||
package tenantprovision
|
||||
|
||||
|
||||
Reference in New Issue
Block a user