mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add endpoint for fetching workspace proxy keys (#14789)
This commit is contained in:
Generated
+72
@@ -7540,6 +7540,34 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/workspaceproxies/me/crypto-keys": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Enterprise"
|
||||
],
|
||||
"summary": "Get workspace proxy crypto keys",
|
||||
"operationId": "get-workspace-proxy-crypto-keys",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/wsproxysdk.CryptoKeysResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/workspaceproxies/me/deregister": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -15955,6 +15983,50 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"wsproxysdk.CryptoKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deletes_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"feature": {
|
||||
"$ref": "#/definitions/wsproxysdk.CryptoKeyFeature"
|
||||
},
|
||||
"secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "integer"
|
||||
},
|
||||
"starts_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"wsproxysdk.CryptoKeyFeature": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"workspace_apps",
|
||||
"oidc_convert",
|
||||
"tailnet_resume"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"CryptoKeyFeatureWorkspaceApp",
|
||||
"CryptoKeyFeatureOIDCConvert",
|
||||
"CryptoKeyFeatureTailnetResume"
|
||||
]
|
||||
},
|
||||
"wsproxysdk.CryptoKeysResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crypto_keys": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/wsproxysdk.CryptoKey"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"wsproxysdk.DeregisterWorkspaceProxyRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Generated
+64
@@ -6668,6 +6668,30 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/workspaceproxies/me/crypto-keys": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Enterprise"],
|
||||
"summary": "Get workspace proxy crypto keys",
|
||||
"operationId": "get-workspace-proxy-crypto-keys",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/wsproxysdk.CryptoKeysResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/workspaceproxies/me/deregister": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -14590,6 +14614,46 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"wsproxysdk.CryptoKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deletes_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"feature": {
|
||||
"$ref": "#/definitions/wsproxysdk.CryptoKeyFeature"
|
||||
},
|
||||
"secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "integer"
|
||||
},
|
||||
"starts_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"wsproxysdk.CryptoKeyFeature": {
|
||||
"type": "string",
|
||||
"enum": ["workspace_apps", "oidc_convert", "tailnet_resume"],
|
||||
"x-enum-varnames": [
|
||||
"CryptoKeyFeatureWorkspaceApp",
|
||||
"CryptoKeyFeatureOIDCConvert",
|
||||
"CryptoKeyFeatureTailnetResume"
|
||||
]
|
||||
},
|
||||
"wsproxysdk.CryptoKeysResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crypto_keys": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/wsproxysdk.CryptoKey"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"wsproxysdk.DeregisterWorkspaceProxyRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -1405,6 +1405,13 @@ func (q *querier) GetCryptoKeys(ctx context.Context) ([]database.CryptoKey, erro
|
||||
return q.db.GetCryptoKeys(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetCryptoKeysByFeature(ctx context.Context, feature database.CryptoKeyFeature) ([]database.CryptoKey, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceCryptoKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetCryptoKeysByFeature(ctx, feature)
|
||||
}
|
||||
|
||||
func (q *querier) GetDBCryptKeys(ctx context.Context) ([]database.DBCryptKey, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -2302,6 +2302,10 @@ func (s *MethodTestSuite) TestCryptoKeys() {
|
||||
DeletesAt: sql.NullTime{Time: time.Now(), Valid: true},
|
||||
}).Asserts(rbac.ResourceCryptoKey, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("GetCryptoKeysByFeature", s.Subtest(func(db database.Store, check *expects) {
|
||||
check.Args(database.CryptoKeyFeatureWorkspaceApps).
|
||||
Asserts(rbac.ResourceCryptoKey, policy.ActionRead)
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestSystemFunctions() {
|
||||
|
||||
@@ -2429,6 +2429,23 @@ func (q *FakeQuerier) GetCryptoKeys(_ context.Context) ([]database.CryptoKey, er
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetCryptoKeysByFeature(_ context.Context, feature database.CryptoKeyFeature) ([]database.CryptoKey, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
keys := make([]database.CryptoKey, 0)
|
||||
for _, key := range q.cryptoKeys {
|
||||
if key.Feature == feature && key.Secret.Valid {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
// We want to return the highest sequence number first.
|
||||
slices.SortFunc(keys, func(i, j database.CryptoKey) int {
|
||||
return int(j.Sequence - i.Sequence)
|
||||
})
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetDBCryptKeys(_ context.Context) ([]database.DBCryptKey, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
@@ -564,6 +564,13 @@ func (m metricsStore) GetCryptoKeys(ctx context.Context) ([]database.CryptoKey,
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) GetCryptoKeysByFeature(ctx context.Context, feature database.CryptoKeyFeature) ([]database.CryptoKey, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetCryptoKeysByFeature(ctx, feature)
|
||||
m.queryLatencies.WithLabelValues("GetCryptoKeysByFeature").Observe(time.Since(start).Seconds())
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) GetDBCryptKeys(ctx context.Context) ([]database.DBCryptKey, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetDBCryptKeys(ctx)
|
||||
|
||||
@@ -1103,6 +1103,21 @@ func (mr *MockStoreMockRecorder) GetCryptoKeys(arg0 any) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCryptoKeys", reflect.TypeOf((*MockStore)(nil).GetCryptoKeys), arg0)
|
||||
}
|
||||
|
||||
// GetCryptoKeysByFeature mocks base method.
|
||||
func (m *MockStore) GetCryptoKeysByFeature(arg0 context.Context, arg1 database.CryptoKeyFeature) ([]database.CryptoKey, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetCryptoKeysByFeature", arg0, arg1)
|
||||
ret0, _ := ret[0].([]database.CryptoKey)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetCryptoKeysByFeature indicates an expected call of GetCryptoKeysByFeature.
|
||||
func (mr *MockStoreMockRecorder) GetCryptoKeysByFeature(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCryptoKeysByFeature", reflect.TypeOf((*MockStore)(nil).GetCryptoKeysByFeature), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetDBCryptKeys mocks base method.
|
||||
func (m *MockStore) GetDBCryptKeys(arg0 context.Context) ([]database.DBCryptKey, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -134,6 +134,7 @@ type sqlcQuerier interface {
|
||||
GetCoordinatorResumeTokenSigningKey(ctx context.Context) (string, error)
|
||||
GetCryptoKeyByFeatureAndSequence(ctx context.Context, arg GetCryptoKeyByFeatureAndSequenceParams) (CryptoKey, error)
|
||||
GetCryptoKeys(ctx context.Context) ([]CryptoKey, error)
|
||||
GetCryptoKeysByFeature(ctx context.Context, feature CryptoKeyFeature) ([]CryptoKey, error)
|
||||
GetDBCryptKeys(ctx context.Context) ([]DBCryptKey, error)
|
||||
GetDERPMeshKey(ctx context.Context) (string, error)
|
||||
GetDefaultOrganization(ctx context.Context) (Organization, error)
|
||||
|
||||
@@ -849,6 +849,44 @@ func (q *sqlQuerier) GetCryptoKeys(ctx context.Context) ([]CryptoKey, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getCryptoKeysByFeature = `-- name: GetCryptoKeysByFeature :many
|
||||
SELECT feature, sequence, secret, secret_key_id, starts_at, deletes_at
|
||||
FROM crypto_keys
|
||||
WHERE feature = $1
|
||||
AND secret IS NOT NULL
|
||||
ORDER BY sequence DESC
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetCryptoKeysByFeature(ctx context.Context, feature CryptoKeyFeature) ([]CryptoKey, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getCryptoKeysByFeature, feature)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CryptoKey
|
||||
for rows.Next() {
|
||||
var i CryptoKey
|
||||
if err := rows.Scan(
|
||||
&i.Feature,
|
||||
&i.Sequence,
|
||||
&i.Secret,
|
||||
&i.SecretKeyID,
|
||||
&i.StartsAt,
|
||||
&i.DeletesAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getLatestCryptoKeyByFeature = `-- name: GetLatestCryptoKeyByFeature :one
|
||||
SELECT feature, sequence, secret, secret_key_id, starts_at, deletes_at
|
||||
FROM crypto_keys
|
||||
|
||||
@@ -3,6 +3,13 @@ SELECT *
|
||||
FROM crypto_keys
|
||||
WHERE secret IS NOT NULL;
|
||||
|
||||
-- name: GetCryptoKeysByFeature :many
|
||||
SELECT *
|
||||
FROM crypto_keys
|
||||
WHERE feature = $1
|
||||
AND secret IS NOT NULL
|
||||
ORDER BY sequence DESC;
|
||||
|
||||
-- name: GetLatestCryptoKeyByFeature :one
|
||||
SELECT *
|
||||
FROM crypto_keys
|
||||
|
||||
Reference in New Issue
Block a user