Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 2 additions & 91 deletions apps/agent/cmd/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,22 @@ package agent
import (
"context"
"fmt"
"net"
"os"
"os/signal"
"runtime/debug"
"strings"
"syscall"

"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fmsg"
"github.com/unkeyed/unkey/apps/agent/pkg/api"
"github.com/unkeyed/unkey/apps/agent/pkg/clickhouse"
"github.com/unkeyed/unkey/apps/agent/pkg/cluster"
"github.com/unkeyed/unkey/apps/agent/pkg/config"
"github.com/unkeyed/unkey/apps/agent/pkg/connect"
"github.com/unkeyed/unkey/apps/agent/pkg/membership"
"github.com/unkeyed/unkey/apps/agent/pkg/metrics"
"github.com/unkeyed/unkey/apps/agent/pkg/profiling"
"github.com/unkeyed/unkey/apps/agent/pkg/prometheus"
"github.com/unkeyed/unkey/apps/agent/pkg/tracing"
"github.com/unkeyed/unkey/apps/agent/pkg/uid"
"github.com/unkeyed/unkey/apps/agent/pkg/version"
"github.com/unkeyed/unkey/apps/agent/services/ratelimit"
"github.com/unkeyed/unkey/apps/agent/services/vault"
"github.com/unkeyed/unkey/apps/agent/services/vault/storage"
storageMiddleware "github.com/unkeyed/unkey/apps/agent/services/vault/storage/middleware"
Expand Down Expand Up @@ -160,81 +154,13 @@ func run(c *cli.Context) error {
return fmt.Errorf("failed to create vault service: %w", err)
}

var clus cluster.Cluster

if cfg.Cluster != nil {

memb, membershipErr := membership.New(membership.Config{
NodeId: cfg.NodeId,
RpcAddr: cfg.Cluster.RpcAddr,
SerfAddr: cfg.Cluster.SerfAddr,
Logger: logger,
})
if membershipErr != nil {
return fmt.Errorf("failed to create membership: %w", membershipErr)
}

var join []string
if cfg.Cluster.Join.Dns != nil {
addrs, lookupErr := net.LookupHost(cfg.Cluster.Join.Dns.AAAA)
if lookupErr != nil {
return fmt.Errorf("failed to lookup dns: %w", lookupErr)
}
logger.Info().Strs("addrs", addrs).Msg("found dns records")
join = addrs
} else if cfg.Cluster.Join.Env != nil {
join = cfg.Cluster.Join.Env.Addrs
}

_, err = memb.Join(join...)
if err != nil {
return fault.Wrap(err, fmsg.With("failed to join cluster"))
}
defer func() {
logger.Info().Msg("leaving membership")
err = memb.Leave()
if err != nil {
logger.Error().Err(err).Msg("failed to leave cluster")
}
}()

clus, err = cluster.New(cluster.Config{
NodeId: cfg.NodeId,
RpcAddr: cfg.Cluster.RpcAddr,
Membership: memb,
Logger: logger,
Metrics: m,
Debug: true,
AuthToken: cfg.Cluster.AuthToken,
})
if err != nil {
return fmt.Errorf("failed to create cluster: %w", err)
}
defer func() {
shutdownErr := clus.Shutdown()
if shutdownErr != nil {
logger.Error().Err(shutdownErr).Msg("failed to shutdown cluster")
}
}()

}

rl, err := ratelimit.New(ratelimit.Config{
Logger: logger,
Metrics: m,
Cluster: clus,
})
if err != nil {
logger.Fatal().Err(err).Msg("failed to create service")
}

srv, err := api.New(api.Config{
NodeId: cfg.NodeId,
Logger: logger,
Ratelimit: rl,
Ratelimit: nil,
Metrics: m,
Clickhouse: ch,
AuthToken: cfg.Cluster.AuthToken,
AuthToken: cfg.AuthToken,
Vault: v,
})
if err != nil {
Expand All @@ -246,17 +172,6 @@ func run(c *cli.Context) error {
return err
}

err = connectSrv.AddService(connect.NewClusterServer(clus, logger))
if err != nil {
return fmt.Errorf("failed to add cluster service: %w", err)

}
err = connectSrv.AddService(connect.NewRatelimitServer(rl, logger, cfg.AuthToken))
if err != nil {
return fmt.Errorf("failed to add ratelimit service: %w", err)
}
logger.Info().Msg("started ratelimit service")

go func() {
err = connectSrv.Listen(fmt.Sprintf(":%s", cfg.RpcPort))
if err != nil {
Expand Down Expand Up @@ -295,10 +210,6 @@ func run(c *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to shutdown service: %w", err)
}
err = clus.Shutdown()
if err != nil {
return fmt.Errorf("failed to shutdown cluster: %w", err)
}

return nil
}
Expand Down
10 changes: 0 additions & 10 deletions apps/agent/config.apprunner.production.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@
"masterKeys": "${VAULT_MASTER_KEYS}"
}
},
"cluster": {
"authToken": "${AUTH_TOKEN}",
"serfAddr": "[${FLY_PRIVATE_IP}]:${SERF_PORT}",
"rpcAddr": "http://${FLY_PRIVATE_IP}:${RPC_PORT}",
"join": {
"env": {
"addrs": []
}
}
},
"heartbeat": {
"interval": 60,
"url": "${HEARTBEAT_URL}"
Expand Down
10 changes: 0 additions & 10 deletions apps/agent/config.apprunner.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,5 @@
"s3AccessKeySecret": "${VAULT_S3_ACCESS_KEY_SECRET}",
"masterKeys": "${VAULT_MASTER_KEYS}"
}
},
"cluster": {
"authToken": "${AUTH_TOKEN}",
"serfAddr": "[${FLY_PRIVATE_IP}]:${SERF_PORT}",
"rpcAddr": "http://${FLY_PRIVATE_IP}:${RPC_PORT}",
"join": {
"env": {
"addrs": []
}
}
}
}
10 changes: 0 additions & 10 deletions apps/agent/config.docker.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@
"authToken": "${AUTH_TOKEN}",
"nodeId": "${NODE_ID}",
"logging": {},
"cluster": {
"authToken": "${AUTH_TOKEN}",
"serfAddr": "${HOSTNAME}:${SERF_PORT}",
"rpcAddr": "${HOSTNAME}:${RPC_PORT}",
"join": {
"env": {
"addrs": ["unkey-agent-1:${SERF_PORT}"]
}
}
},
"services": {
"vault": {
"s3Url": "${VAULT_S3_URL}",
Expand Down
10 changes: 0 additions & 10 deletions apps/agent/config.production.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@
"masterKeys": "${VAULT_MASTER_KEYS}"
}
},
"cluster": {
"authToken": "${AUTH_TOKEN}",
"serfAddr": "[${FLY_PRIVATE_IP}]:${SERF_PORT}",
"rpcAddr": "http://${FLY_PRIVATE_IP}:${RPC_PORT}",
"join": {
"dns": {
"aaaa": "${FLY_APP_NAME}.internal"
}
}
},
"heartbeat": {
"interval": 60,
"url": "${HEARTBEAT_URL}"
Expand Down
10 changes: 0 additions & 10 deletions apps/agent/config.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,6 @@
"masterKeys": "${VAULT_MASTER_KEYS}"
}
},
"cluster": {
"authToken": "${AUTH_TOKEN}",
"serfAddr": "[${FLY_PRIVATE_IP}]:${SERF_PORT}",
"rpcAddr": "http://${FLY_PRIVATE_IP}:${RPC_PORT}",
"join": {
"dns": {
"aaaa": "${FLY_APP_NAME}.internal"
}
}
},
"prometheus": {
"path": "/metrics",
"port": 2112
Expand Down
7 changes: 6 additions & 1 deletion apps/api/src/routes/v1_keys_getVerifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ export const registerV1KeysGetVerifications = (app: App) =>
if (!dbRes) {
return [];
}
return dbRes.map((key) => ({ key, api: key.keyAuth.api, ratelimits: key.ratelimits }));
return dbRes.map((key) => ({
key,
api: key.keyAuth.api,
ratelimits: key.ratelimits,
}));
});
if (keys.err) {
throw new UnkeyApiError({
Expand Down Expand Up @@ -238,6 +242,7 @@ export const registerV1KeysGetVerifications = (app: App) =>
keyIds: null,
outcomes: null,
names: null,
tags: null,
})
.catch((err) => {
throw new Error(err.message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const useFetchVerificationTimeseries = (apiId: string | null) => {
outcomes: { filters: [] },
names: { filters: [] },
identities: { filters: [] },
tags: null,
apiId: apiId ?? "",
since: "",
};
Expand Down Expand Up @@ -99,6 +100,16 @@ export const useFetchVerificationTimeseries = (apiId: string | null) => {
}
break;
}

case "tags": {
if (typeof filter.value === "string" && filter.value.trim()) {
params.tags = {
operator,
value: filter.value,
};
}
break;
}
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export const keysOverviewQueryTimeseriesPayload = z.object({
),
})
.nullable(),
tags: z
.object({
operator: keysOverviewFilterOperatorEnum,
value: z.string(),
})
.nullable(),
Comment on lines +53 to +58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider schema consistency with other filter fields.

The tags field structure differs from other filter fields (keyIds, names, identities) which use arrays of filter objects. This inconsistency may limit the ability to apply multiple tag filters simultaneously.

Consider aligning the tags field structure with other filter fields:

-  tags: z
-    .object({
-      operator: keysOverviewFilterOperatorEnum,
-      value: z.string(),
-    })
-    .nullable(),
+  tags: z
+    .object({
+      filters: z.array(
+        z.object({
+          operator: keysOverviewFilterOperatorEnum,
+          value: z.string(),
+        }),
+      ),
+    })
+    .nullable(),

This would maintain consistency with the existing filter pattern and allow multiple tag filters if needed.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tags: z
.object({
operator: keysOverviewFilterOperatorEnum,
value: z.string(),
})
.nullable(),
tags: z
.object({
filters: z.array(
z.object({
operator: keysOverviewFilterOperatorEnum,
value: z.string(),
}),
),
})
.nullable(),
🤖 Prompt for AI Agents
In
apps/dashboard/app/(app)/apis/[apiId]/_overview/components/charts/bar-chart/query-timeseries.schema.ts
around lines 53 to 58, the tags field is defined as a single nullable filter
object, unlike other filter fields such as keyIds, names, and identities which
use arrays of filter objects. To fix this, change the tags field to be an array
of filter objects (each with operator and value) instead of a single object,
ensuring it matches the pattern used by other filters and supports multiple tag
filters simultaneously.

});

export type KeysOverviewQueryTimeseriesPayload = z.infer<typeof keysOverviewQueryTimeseriesPayload>;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const useFetchActiveKeysTimeseries = (apiId: string | null) => {
outcomes: { filters: [] },
names: { filters: [] },
identities: { filters: [] },
tags: null,
apiId: apiId ?? "",
since: "",
};
Expand Down Expand Up @@ -99,6 +100,16 @@ export const useFetchActiveKeysTimeseries = (apiId: string | null) => {
}
break;
}

case "tags": {
if (typeof filter.value === "string" && filter.value.trim()) {
params.tags = {
operator,
value: filter.value,
};
}
break;
}
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ export const LogsFilters = () => {
const activeNameFilter = filters.find((f) => f.field === "names");
const activeIdentityFilter = filters.find((f) => f.field === "identities");
const activeKeyIdsFilter = filters.find((f) => f.field === "keyIds");
const activeTagsFilter = filters.find((f) => f.field === "tags");
const keyIdOptions = keysOverviewFilterFieldConfig.keyIds.operators.map((op) => ({
id: op,
label: op,
}));
const tagsOptions = keysOverviewFilterFieldConfig.tags.operators.map((op) => ({
id: op,
label: op,
}));
return (
<FiltersPopover
open={open}
Expand Down Expand Up @@ -107,6 +112,32 @@ export const LogsFilters = () => {
/>
),
},
{
id: "tags",
label: "Tags",
shortcut: "t",
component: (
<FilterOperatorInput
label="Tags"
options={tagsOptions}
defaultOption={activeTagsFilter?.operator}
defaultText={activeTagsFilter?.value as string}
onApply={(id, text) => {
const activeFiltersWithoutTags = filters.filter((f) => f.field !== "tags");
updateFilters([
...activeFiltersWithoutTags,
{
field: "tags",
id: crypto.randomUUID(),
operator: id,
value: text,
},
]);
setOpen(false);
}}
/>
),
},
{
id: "outcomes",
label: "Outcomes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ export const KeysOverviewLogDetails = ({
: "Unlimited",
};

const tags =
log.tags && log.tags.length > 0 ? { Tags: log.tags.join(", ") } : { "No tags": null };

const identity = log.key_details.identity
? { "External ID": log.key_details.identity.external_id || "N/A" }
: { "No identity connected": null };
Expand All @@ -111,6 +114,7 @@ export const KeysOverviewLogDetails = ({
<LogSection title="Limits" details={limits} />
<LogSection title="Identifiers" details={identifiers} />
<LogSection title="Identity" details={identity} />
<LogSection title="Tags" details={tags} />
<RolesSection roles={log.key_details.roles || []} />
<PermissionsSection permissions={log.key_details.permissions || []} />
<LogSection title="Meta" details={metaString} />
Expand Down
Loading