Thanks to visit codestin.com
Credit goes to github.com

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
14 changes: 2 additions & 12 deletions coderd/aibridged.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io"
"net/http"

"golang.org/x/xerrors"
"storj.io/drpc/drpcmux"
"storj.io/drpc/drpcserver"

Expand Down Expand Up @@ -71,17 +70,8 @@ func (api *API) CreateInMemoryAIBridgeServer(dialCtx context.Context) (client ai
if err != nil {
return nil, err
}
err = aibridgedproto.DRPCRegisterRecorder(mux, srv)
if err != nil {
return nil, xerrors.Errorf("register recorder service: %w", err)
}
err = aibridgedproto.DRPCRegisterMCPConfigurator(mux, srv)
if err != nil {
return nil, xerrors.Errorf("register MCP configurator service: %w", err)
}
err = aibridgedproto.DRPCRegisterAuthorizer(mux, srv)
if err != nil {
return nil, xerrors.Errorf("register key validator service: %w", err)
if err := aibridgedserver.Register(mux, srv); err != nil {
return nil, err
}
server := drpcserver.NewWithOptions(&tracing.DRPCHandler{Handler: mux},
drpcserver.Options{
Expand Down
19 changes: 19 additions & 0 deletions coderd/aibridged/proto/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package proto

import "github.com/coder/coder/v2/apiversion"

// Version history:
//
// API v1.0:
// - Initial version. Serves the Recorder, MCPConfigurator, and Authorizer
// services to embedded and standalone AI Gateway daemons.
const (
CurrentMajor = 1
CurrentMinor = 0
)

// CurrentVersion is the current aibridged API version.
// Breaking changes to the aibridged API **MUST** increment CurrentMajor above.
// Non-breaking changes to the aibridged API **MUST** increment CurrentMinor
// above.
var CurrentVersion = apiversion.New(CurrentMajor, CurrentMinor)
14 changes: 7 additions & 7 deletions coderd/aibridgedserver/aibridgedserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,13 +594,13 @@ externalAuthLoop:
// IsAuthorized validates a given Coder API key and returns the user ID to which it belongs (if valid).
//
// SECURITY: when in.KeyId is set (the "delegated" path), this method trusts the
// caller's claim of identity and skips the key-secret check. This is safe only
// because the DRPCServer is reachable solely via the in-process
// [aibridged.MemTransportPipe]; the handler itself cannot tell whether it was
// invoked over the in-memory pipe or a network socket. If this RPC is ever
// exposed over a network boundary, any caller who knows a valid 10-char key ID
// (which is not secret) could authenticate as the key's owner without the
// secret. Do not bind this DRPCServer to a network listener.
// caller's claim of identity and skips the key-secret check. This DRPCServer is
// reachable both in-process via [aibridged.MemTransportPipe] and over the network
// via the /api/v2/ai-gateway/serve endpoint. That endpoint admits only holders of
// AI Gateway key, which are fully trusted. Standalone AI Gateway authenticates its
// own users and acts on their behalf, much like a provisioner daemon. A Gateway key
// holder can therefore act as any user without that user's secret. Per-user
// authorization on this surface is a known gap.
//
// NOTE: this should really be using the code from [httpmw.ExtractAPIKey]. That function not only validates the key
// but handles many other cases like updating last used, expiry, etc. This code does not currently use it for
Expand Down
25 changes: 25 additions & 0 deletions coderd/aibridgedserver/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package aibridgedserver

import (
"golang.org/x/xerrors"
"storj.io/drpc/drpcmux"

"github.com/coder/coder/v2/coderd/aibridged/proto"
)

// Register registers the Recorder, MCPConfigurator, and Authorizer DRPC
// services backed by srv onto mux. It is shared by the embedded in-memory
// server and the standalone /api/v2/ai-gateway/serve WebSocket handler so both
// expose an identical service set.
func Register(mux *drpcmux.Mux, srv *Server) error {
if err := proto.DRPCRegisterRecorder(mux, srv); err != nil {
return xerrors.Errorf("register recorder service: %w", err)
}
if err := proto.DRPCRegisterMCPConfigurator(mux, srv); err != nil {
return xerrors.Errorf("register MCP configurator service: %w", err)
}
if err := proto.DRPCRegisterAuthorizer(mux, srv); err != nil {
return xerrors.Errorf("register authorizer service: %w", err)
}
return nil
}
24 changes: 24 additions & 0 deletions coderd/apidoc/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions coderd/apidoc/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ type Options struct {
// @securitydefinitions.apiKey CoderSessionToken
// @in header
// @name Coder-Session-Token

// @securitydefinitions.apiKey AIGatewayKey
// @in header
// @name X-AI-Governance-Gateway-Key
// New constructs a Coder API handler.
func New(options *Options) *API {
if options == nil {
Expand Down
5 changes: 5 additions & 0 deletions coderd/coderdtest/swaggerparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ func assertSecurityDefined(t *testing.T, comment SwaggerComment) {
comment.router == "/api/v2/init-script/{os}/{arch}" {
return // endpoints do not require authorization
}
if comment.router == "/api/v2/ai-gateway/serve" {
assert.Equal(t, "AIGatewayKey", comment.security, "@Security must be AIGatewayKey")
return
}

assert.Containsf(t, authorizedSecurityTags, comment.security, "@Security must be either of these options: %v", authorizedSecurityTags)
}

Expand Down
3 changes: 3 additions & 0 deletions codersdk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ const (
// ProvisionerDaemonKey contains the authentication key for an external provisioner daemon
ProvisionerDaemonKey = "Coder-Provisioner-Daemon-Key"

// AIGatewayKeyHeader contains the authentication key for a standalone AI Gateway replica.
AIGatewayKeyHeader = "X-Coder-AI-Governance-Gateway-Key"

// BuildVersionHeader contains build information of Coder.
BuildVersionHeader = "X-Coder-Build-Version"

Expand Down
4 changes: 4 additions & 0 deletions codersdk/drpcsdk/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ const (
// MaxMessageSize is the maximum payload size that can be
// transported without error.
MaxMessageSize = 4 << 20

// YamuxDefaultStreamWindowSize matches hashicorp/yamux's unexported
// initialStreamWindow, which DefaultConfig uses as MaxStreamWindowSize.
YamuxDefaultStreamWindowSize = 256 * 1024
)

func DefaultDRPCOptions(options *drpcmanager.Options) drpcmanager.Options {
Expand Down
4 changes: 1 addition & 3 deletions codersdk/provisionerdaemons.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,11 @@ func (c *Client) ServeProvisionerDaemon(ctx context.Context, req ServeProvisione
}
return nil, ReadBodyAsError(res)
}
// Align with the frame size of yamux.
conn.SetReadLimit(256 * 1024)

config := yamux.DefaultConfig()
config.LogOutput = io.Discard
// Use background context because caller should close the client.
_, wsNetConn := WebsocketNetConn(context.Background(), conn, websocket.MessageBinary)
conn.SetReadLimit(drpcsdk.YamuxDefaultStreamWindowSize)
session, err := yamux.Client(wsNetConn, config)
if err != nil {
_ = conn.Close(websocket.StatusGoingAway, "")
Expand Down
20 changes: 20 additions & 0 deletions docs/reference/api/enterprise.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading