diff --git a/doc/index.html b/doc/index.html
index d56b3155..461c9073 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -1585,6 +1585,14 @@
Table of Contents
metalstack/admin/v2/token.proto
+ -
+ MTokenServiceCreateRequest
+
+
+ -
+ MTokenServiceCreateResponse
+
+
-
MTokenServiceListRequest
@@ -13149,6 +13157,68 @@
+
+ TokenServiceCreateRequest is the request payload to create a token
+
+
+
+
+ | Field | Type | Label | Description |
+
+
+
+
+ | user |
+ string |
+ optional |
+ User this token should be created for, if omitted, user is derived from caller |
+
+
+
+ | token |
+ metalstack.api.v2.Token |
+ |
+ Token which was should be created |
+
+
+
+
+
+
+
+
+
+
+ TokenServiceCreateResponse is the response payload of a token create request
+
+
+
+
+ | Field | Type | Label | Description |
+
+
+
+
+ | token |
+ metalstack.api.v2.Token |
+ |
+ Token which was created |
+
+
+
+ | secret |
+ string |
+ |
+ Secret is the body if the jwt token, should be used in api requests as bearer token |
+
+
+
+
+
+
+
+
+
TokenServiceListRequest is the request payload for the token list request
@@ -13263,6 +13333,13 @@
Revoke a token |
+
+ | Create |
+ TokenServiceCreateRequest |
+ TokenServiceCreateResponse |
+ Create a token to authenticate against the platform, the secret will be only visible in the response |
+
+
diff --git a/go/metalstack/admin/v2/adminv2connect/token.connect.go b/go/metalstack/admin/v2/adminv2connect/token.connect.go
index 01c7fe5b..6c906c60 100644
--- a/go/metalstack/admin/v2/adminv2connect/token.connect.go
+++ b/go/metalstack/admin/v2/adminv2connect/token.connect.go
@@ -37,6 +37,8 @@ const (
TokenServiceListProcedure = "/metalstack.admin.v2.TokenService/List"
// TokenServiceRevokeProcedure is the fully-qualified name of the TokenService's Revoke RPC.
TokenServiceRevokeProcedure = "/metalstack.admin.v2.TokenService/Revoke"
+ // TokenServiceCreateProcedure is the fully-qualified name of the TokenService's Create RPC.
+ TokenServiceCreateProcedure = "/metalstack.admin.v2.TokenService/Create"
)
// TokenServiceClient is a client for the metalstack.admin.v2.TokenService service.
@@ -45,6 +47,8 @@ type TokenServiceClient interface {
List(context.Context, *v2.TokenServiceListRequest) (*v2.TokenServiceListResponse, error)
// Revoke a token
Revoke(context.Context, *v2.TokenServiceRevokeRequest) (*v2.TokenServiceRevokeResponse, error)
+ // Create a token to authenticate against the platform, the secret will be only visible in the response
+ Create(context.Context, *v2.TokenServiceCreateRequest) (*v2.TokenServiceCreateResponse, error)
}
// NewTokenServiceClient constructs a client for the metalstack.admin.v2.TokenService service. By
@@ -70,6 +74,12 @@ func NewTokenServiceClient(httpClient connect.HTTPClient, baseURL string, opts .
connect.WithSchema(tokenServiceMethods.ByName("Revoke")),
connect.WithClientOptions(opts...),
),
+ create: connect.NewClient[v2.TokenServiceCreateRequest, v2.TokenServiceCreateResponse](
+ httpClient,
+ baseURL+TokenServiceCreateProcedure,
+ connect.WithSchema(tokenServiceMethods.ByName("Create")),
+ connect.WithClientOptions(opts...),
+ ),
}
}
@@ -77,6 +87,7 @@ func NewTokenServiceClient(httpClient connect.HTTPClient, baseURL string, opts .
type tokenServiceClient struct {
list *connect.Client[v2.TokenServiceListRequest, v2.TokenServiceListResponse]
revoke *connect.Client[v2.TokenServiceRevokeRequest, v2.TokenServiceRevokeResponse]
+ create *connect.Client[v2.TokenServiceCreateRequest, v2.TokenServiceCreateResponse]
}
// List calls metalstack.admin.v2.TokenService.List.
@@ -97,12 +108,23 @@ func (c *tokenServiceClient) Revoke(ctx context.Context, req *v2.TokenServiceRev
return nil, err
}
+// Create calls metalstack.admin.v2.TokenService.Create.
+func (c *tokenServiceClient) Create(ctx context.Context, req *v2.TokenServiceCreateRequest) (*v2.TokenServiceCreateResponse, error) {
+ response, err := c.create.CallUnary(ctx, connect.NewRequest(req))
+ if response != nil {
+ return response.Msg, err
+ }
+ return nil, err
+}
+
// TokenServiceHandler is an implementation of the metalstack.admin.v2.TokenService service.
type TokenServiceHandler interface {
// List tokens
List(context.Context, *v2.TokenServiceListRequest) (*v2.TokenServiceListResponse, error)
// Revoke a token
Revoke(context.Context, *v2.TokenServiceRevokeRequest) (*v2.TokenServiceRevokeResponse, error)
+ // Create a token to authenticate against the platform, the secret will be only visible in the response
+ Create(context.Context, *v2.TokenServiceCreateRequest) (*v2.TokenServiceCreateResponse, error)
}
// NewTokenServiceHandler builds an HTTP handler from the service implementation. It returns the
@@ -124,12 +146,20 @@ func NewTokenServiceHandler(svc TokenServiceHandler, opts ...connect.HandlerOpti
connect.WithSchema(tokenServiceMethods.ByName("Revoke")),
connect.WithHandlerOptions(opts...),
)
+ tokenServiceCreateHandler := connect.NewUnaryHandlerSimple(
+ TokenServiceCreateProcedure,
+ svc.Create,
+ connect.WithSchema(tokenServiceMethods.ByName("Create")),
+ connect.WithHandlerOptions(opts...),
+ )
return "/metalstack.admin.v2.TokenService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case TokenServiceListProcedure:
tokenServiceListHandler.ServeHTTP(w, r)
case TokenServiceRevokeProcedure:
tokenServiceRevokeHandler.ServeHTTP(w, r)
+ case TokenServiceCreateProcedure:
+ tokenServiceCreateHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
@@ -146,3 +176,7 @@ func (UnimplementedTokenServiceHandler) List(context.Context, *v2.TokenServiceLi
func (UnimplementedTokenServiceHandler) Revoke(context.Context, *v2.TokenServiceRevokeRequest) (*v2.TokenServiceRevokeResponse, error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("metalstack.admin.v2.TokenService.Revoke is not implemented"))
}
+
+func (UnimplementedTokenServiceHandler) Create(context.Context, *v2.TokenServiceCreateRequest) (*v2.TokenServiceCreateResponse, error) {
+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("metalstack.admin.v2.TokenService.Create is not implemented"))
+}
diff --git a/go/metalstack/admin/v2/token.pb.go b/go/metalstack/admin/v2/token.pb.go
index 9ca22ac9..072ed234 100644
--- a/go/metalstack/admin/v2/token.pb.go
+++ b/go/metalstack/admin/v2/token.pb.go
@@ -207,6 +207,116 @@ func (*TokenServiceRevokeResponse) Descriptor() ([]byte, []int) {
return file_metalstack_admin_v2_token_proto_rawDescGZIP(), []int{3}
}
+// TokenServiceCreateRequest is the request payload to create a token
+type TokenServiceCreateRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ // User this token should be created for, if omitted, user is derived from caller
+ User *string `protobuf:"bytes,1,opt,name=user,proto3,oneof" json:"user,omitempty"`
+ // Token which was should be created
+ Token *v2.Token `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *TokenServiceCreateRequest) Reset() {
+ *x = TokenServiceCreateRequest{}
+ mi := &file_metalstack_admin_v2_token_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *TokenServiceCreateRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TokenServiceCreateRequest) ProtoMessage() {}
+
+func (x *TokenServiceCreateRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_metalstack_admin_v2_token_proto_msgTypes[4]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TokenServiceCreateRequest.ProtoReflect.Descriptor instead.
+func (*TokenServiceCreateRequest) Descriptor() ([]byte, []int) {
+ return file_metalstack_admin_v2_token_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *TokenServiceCreateRequest) GetUser() string {
+ if x != nil && x.User != nil {
+ return *x.User
+ }
+ return ""
+}
+
+func (x *TokenServiceCreateRequest) GetToken() *v2.Token {
+ if x != nil {
+ return x.Token
+ }
+ return nil
+}
+
+// TokenServiceCreateResponse is the response payload of a token create request
+type TokenServiceCreateResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ // Token which was created
+ Token *v2.Token `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
+ // Secret is the body if the jwt token, should be used in api requests as bearer token
+ Secret string `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *TokenServiceCreateResponse) Reset() {
+ *x = TokenServiceCreateResponse{}
+ mi := &file_metalstack_admin_v2_token_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *TokenServiceCreateResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TokenServiceCreateResponse) ProtoMessage() {}
+
+func (x *TokenServiceCreateResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_metalstack_admin_v2_token_proto_msgTypes[5]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TokenServiceCreateResponse.ProtoReflect.Descriptor instead.
+func (*TokenServiceCreateResponse) Descriptor() ([]byte, []int) {
+ return file_metalstack_admin_v2_token_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *TokenServiceCreateResponse) GetToken() *v2.Token {
+ if x != nil {
+ return x.Token
+ }
+ return nil
+}
+
+func (x *TokenServiceCreateResponse) GetSecret() string {
+ if x != nil {
+ return x.Secret
+ }
+ return ""
+}
+
var File_metalstack_admin_v2_token_proto protoreflect.FileDescriptor
const file_metalstack_admin_v2_token_proto_rawDesc = "" +
@@ -221,10 +331,19 @@ const file_metalstack_admin_v2_token_proto_rawDesc = "" +
"\x04uuid\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x04uuid\x12\x1e\n" +
"\x04user\x18\x02 \x01(\tB\n" +
"\xbaH\ar\x05\x10\x02\x18\x80\x04R\x04user\"\x1c\n" +
- "\x1aTokenServiceRevokeResponse2\xed\x01\n" +
+ "\x1aTokenServiceRevokeResponse\"y\n" +
+ "\x19TokenServiceCreateRequest\x12#\n" +
+ "\x04user\x18\x01 \x01(\tB\n" +
+ "\xbaH\ar\x05\x10\x02\x18\x80\x04H\x00R\x04user\x88\x01\x01\x12.\n" +
+ "\x05token\x18\x02 \x01(\v2\x18.metalstack.api.v2.TokenR\x05tokenB\a\n" +
+ "\x05_user\"d\n" +
+ "\x1aTokenServiceCreateResponse\x12.\n" +
+ "\x05token\x18\x01 \x01(\v2\x18.metalstack.api.v2.TokenR\x05token\x12\x16\n" +
+ "\x06secret\x18\x02 \x01(\tR\x06secret2\xdf\x02\n" +
"\fTokenService\x12k\n" +
"\x04List\x12,.metalstack.admin.v2.TokenServiceListRequest\x1a-.metalstack.admin.v2.TokenServiceListResponse\"\x06\xd2\xf3\x18\x02\x01\x02\x12p\n" +
- "\x06Revoke\x12..metalstack.admin.v2.TokenServiceRevokeRequest\x1a/.metalstack.admin.v2.TokenServiceRevokeResponse\"\x05\xd2\xf3\x18\x01\x01B\xce\x01\n" +
+ "\x06Revoke\x12..metalstack.admin.v2.TokenServiceRevokeRequest\x1a/.metalstack.admin.v2.TokenServiceRevokeResponse\"\x05\xd2\xf3\x18\x01\x01\x12p\n" +
+ "\x06Create\x12..metalstack.admin.v2.TokenServiceCreateRequest\x1a/.metalstack.admin.v2.TokenServiceCreateResponse\"\x05\xd2\xf3\x18\x01\x01B\xce\x01\n" +
"\x17com.metalstack.admin.v2B\n" +
"TokenProtoP\x01Z9github.com/metal-stack/api/go/metalstack/admin/v2;adminv2\xa2\x02\x03MAX\xaa\x02\x13Metalstack.Admin.V2\xca\x02\x13Metalstack\\Admin\\V2\xe2\x02\x1fMetalstack\\Admin\\V2\\GPBMetadata\xea\x02\x15Metalstack::Admin::V2b\x06proto3"
@@ -240,25 +359,31 @@ func file_metalstack_admin_v2_token_proto_rawDescGZIP() []byte {
return file_metalstack_admin_v2_token_proto_rawDescData
}
-var file_metalstack_admin_v2_token_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_metalstack_admin_v2_token_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_metalstack_admin_v2_token_proto_goTypes = []any{
(*TokenServiceListRequest)(nil), // 0: metalstack.admin.v2.TokenServiceListRequest
(*TokenServiceListResponse)(nil), // 1: metalstack.admin.v2.TokenServiceListResponse
(*TokenServiceRevokeRequest)(nil), // 2: metalstack.admin.v2.TokenServiceRevokeRequest
(*TokenServiceRevokeResponse)(nil), // 3: metalstack.admin.v2.TokenServiceRevokeResponse
- (*v2.Token)(nil), // 4: metalstack.api.v2.Token
+ (*TokenServiceCreateRequest)(nil), // 4: metalstack.admin.v2.TokenServiceCreateRequest
+ (*TokenServiceCreateResponse)(nil), // 5: metalstack.admin.v2.TokenServiceCreateResponse
+ (*v2.Token)(nil), // 6: metalstack.api.v2.Token
}
var file_metalstack_admin_v2_token_proto_depIdxs = []int32{
- 4, // 0: metalstack.admin.v2.TokenServiceListResponse.tokens:type_name -> metalstack.api.v2.Token
- 0, // 1: metalstack.admin.v2.TokenService.List:input_type -> metalstack.admin.v2.TokenServiceListRequest
- 2, // 2: metalstack.admin.v2.TokenService.Revoke:input_type -> metalstack.admin.v2.TokenServiceRevokeRequest
- 1, // 3: metalstack.admin.v2.TokenService.List:output_type -> metalstack.admin.v2.TokenServiceListResponse
- 3, // 4: metalstack.admin.v2.TokenService.Revoke:output_type -> metalstack.admin.v2.TokenServiceRevokeResponse
- 3, // [3:5] is the sub-list for method output_type
- 1, // [1:3] is the sub-list for method input_type
- 1, // [1:1] is the sub-list for extension type_name
- 1, // [1:1] is the sub-list for extension extendee
- 0, // [0:1] is the sub-list for field type_name
+ 6, // 0: metalstack.admin.v2.TokenServiceListResponse.tokens:type_name -> metalstack.api.v2.Token
+ 6, // 1: metalstack.admin.v2.TokenServiceCreateRequest.token:type_name -> metalstack.api.v2.Token
+ 6, // 2: metalstack.admin.v2.TokenServiceCreateResponse.token:type_name -> metalstack.api.v2.Token
+ 0, // 3: metalstack.admin.v2.TokenService.List:input_type -> metalstack.admin.v2.TokenServiceListRequest
+ 2, // 4: metalstack.admin.v2.TokenService.Revoke:input_type -> metalstack.admin.v2.TokenServiceRevokeRequest
+ 4, // 5: metalstack.admin.v2.TokenService.Create:input_type -> metalstack.admin.v2.TokenServiceCreateRequest
+ 1, // 6: metalstack.admin.v2.TokenService.List:output_type -> metalstack.admin.v2.TokenServiceListResponse
+ 3, // 7: metalstack.admin.v2.TokenService.Revoke:output_type -> metalstack.admin.v2.TokenServiceRevokeResponse
+ 5, // 8: metalstack.admin.v2.TokenService.Create:output_type -> metalstack.admin.v2.TokenServiceCreateResponse
+ 6, // [6:9] is the sub-list for method output_type
+ 3, // [3:6] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
}
func init() { file_metalstack_admin_v2_token_proto_init() }
@@ -267,13 +392,14 @@ func file_metalstack_admin_v2_token_proto_init() {
return
}
file_metalstack_admin_v2_token_proto_msgTypes[0].OneofWrappers = []any{}
+ file_metalstack_admin_v2_token_proto_msgTypes[4].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metalstack_admin_v2_token_proto_rawDesc), len(file_metalstack_admin_v2_token_proto_rawDesc)),
NumEnums: 0,
- NumMessages: 4,
+ NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/go/permissions/servicepermissions.go b/go/permissions/servicepermissions.go
index e7c1901c..efa92cc1 100755
--- a/go/permissions/servicepermissions.go
+++ b/go/permissions/servicepermissions.go
@@ -73,6 +73,7 @@ func GetServicePermissions() *ServicePermissions {
"/metalstack.admin.v2.TenantService/List",
"/metalstack.admin.v2.TokenService/List",
"/metalstack.admin.v2.TokenService/Revoke",
+ "/metalstack.admin.v2.TokenService/Create",
},
"ADMIN_ROLE_VIEWER": []string{
"/metalstack.admin.v2.ImageService/Usage",
@@ -211,6 +212,7 @@ func GetServicePermissions() *ServicePermissions {
"/metalstack.admin.v2.SwitchService/Update": true,
"/metalstack.admin.v2.TenantService/Create": true,
"/metalstack.admin.v2.TenantService/List": true,
+ "/metalstack.admin.v2.TokenService/Create": true,
"/metalstack.admin.v2.TokenService/List": true,
"/metalstack.admin.v2.TokenService/Revoke": true,
"/metalstack.api.v2.FilesystemService/Get": true,
@@ -345,6 +347,7 @@ func GetServicePermissions() *ServicePermissions {
"/metalstack.admin.v2.SwitchService/Update": true,
"/metalstack.admin.v2.TenantService/Create": true,
"/metalstack.admin.v2.TenantService/List": true,
+ "/metalstack.admin.v2.TokenService/Create": true,
"/metalstack.admin.v2.TokenService/List": true,
"/metalstack.admin.v2.TokenService/Revoke": true,
},
@@ -423,6 +426,7 @@ func GetServicePermissions() *ServicePermissions {
"/metalstack.admin.v2.SwitchService/Update": true,
"/metalstack.admin.v2.TenantService/Create": true,
"/metalstack.admin.v2.TenantService/List": true,
+ "/metalstack.admin.v2.TokenService/Create": true,
"/metalstack.admin.v2.TokenService/List": true,
"/metalstack.admin.v2.TokenService/Revoke": true,
"/metalstack.api.v2.FilesystemService/Get": false,
diff --git a/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceClient.go b/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceClient.go
index b56f164c..7724fbf4 100644
--- a/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceClient.go
+++ b/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceClient.go
@@ -15,6 +15,36 @@ type TokenServiceClient struct {
mock.Mock
}
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *TokenServiceClient) Create(_a0 context.Context, _a1 *adminv2.TokenServiceCreateRequest) (*adminv2.TokenServiceCreateResponse, error) {
+ ret := _m.Called(_a0, _a1)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Create")
+ }
+
+ var r0 *adminv2.TokenServiceCreateResponse
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *adminv2.TokenServiceCreateRequest) (*adminv2.TokenServiceCreateResponse, error)); ok {
+ return rf(_a0, _a1)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *adminv2.TokenServiceCreateRequest) *adminv2.TokenServiceCreateResponse); ok {
+ r0 = rf(_a0, _a1)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*adminv2.TokenServiceCreateResponse)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *adminv2.TokenServiceCreateRequest) error); ok {
+ r1 = rf(_a0, _a1)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// List provides a mock function with given fields: _a0, _a1
func (_m *TokenServiceClient) List(_a0 context.Context, _a1 *adminv2.TokenServiceListRequest) (*adminv2.TokenServiceListResponse, error) {
ret := _m.Called(_a0, _a1)
diff --git a/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceHandler.go b/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceHandler.go
index 2015250c..8caa0f6f 100644
--- a/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceHandler.go
+++ b/go/tests/mocks/metalstack/admin/v2/adminv2connect/TokenServiceHandler.go
@@ -15,6 +15,36 @@ type TokenServiceHandler struct {
mock.Mock
}
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *TokenServiceHandler) Create(_a0 context.Context, _a1 *adminv2.TokenServiceCreateRequest) (*adminv2.TokenServiceCreateResponse, error) {
+ ret := _m.Called(_a0, _a1)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Create")
+ }
+
+ var r0 *adminv2.TokenServiceCreateResponse
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *adminv2.TokenServiceCreateRequest) (*adminv2.TokenServiceCreateResponse, error)); ok {
+ return rf(_a0, _a1)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *adminv2.TokenServiceCreateRequest) *adminv2.TokenServiceCreateResponse); ok {
+ r0 = rf(_a0, _a1)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*adminv2.TokenServiceCreateResponse)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *adminv2.TokenServiceCreateRequest) error); ok {
+ r1 = rf(_a0, _a1)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// List provides a mock function with given fields: _a0, _a1
func (_m *TokenServiceHandler) List(_a0 context.Context, _a1 *adminv2.TokenServiceListRequest) (*adminv2.TokenServiceListResponse, error) {
ret := _m.Called(_a0, _a1)
diff --git a/proto/metalstack/admin/v2/token.proto b/proto/metalstack/admin/v2/token.proto
index ed9a6ab7..b79a04d4 100644
--- a/proto/metalstack/admin/v2/token.proto
+++ b/proto/metalstack/admin/v2/token.proto
@@ -17,6 +17,10 @@ service TokenService {
rpc Revoke(TokenServiceRevokeRequest) returns (TokenServiceRevokeResponse) {
option (metalstack.api.v2.admin_roles) = ADMIN_ROLE_EDITOR;
}
+ // Create a token to authenticate against the platform, the secret will be only visible in the response
+ rpc Create(TokenServiceCreateRequest) returns (TokenServiceCreateResponse) {
+ option (metalstack.api.v2.admin_roles) = ADMIN_ROLE_EDITOR;
+ }
}
// TokenServiceListRequest is the request payload for the token list request
@@ -44,3 +48,22 @@ message TokenServiceRevokeRequest {
// TokenServiceRevokeResponse is the response payload for the token revoke request
message TokenServiceRevokeResponse {}
+
+// TokenServiceCreateRequest is the request payload to create a token
+message TokenServiceCreateRequest {
+ // User this token should be created for, if omitted, user is derived from caller
+ optional string user = 1 [(buf.validate.field).string = {
+ min_len: 2
+ max_len: 512
+ }];
+ // Token which was should be created
+ metalstack.api.v2.Token token = 2;
+}
+
+// TokenServiceCreateResponse is the response payload of a token create request
+message TokenServiceCreateResponse {
+ // Token which was created
+ metalstack.api.v2.Token token = 1;
+ // Secret is the body if the jwt token, should be used in api requests as bearer token
+ string secret = 2;
+}
diff --git a/python/metalstack/admin/v2/token_connect.py b/python/metalstack/admin/v2/token_connect.py
index 14d2f31f..bd42a6da 100644
--- a/python/metalstack/admin/v2/token_connect.py
+++ b/python/metalstack/admin/v2/token_connect.py
@@ -22,6 +22,9 @@ async def list(self, request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenSe
async def revoke(self, request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceRevokeRequest, ctx: RequestContext) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceRevokeResponse:
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
+ async def create(self, request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest, ctx: RequestContext) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse:
+ raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
+
class TokenServiceASGIApplication(ConnectASGIApplication):
def __init__(self, service: TokenService, *, interceptors: Iterable[Interceptor]=(), read_max_bytes: int | None = None) -> None:
@@ -47,6 +50,16 @@ def __init__(self, service: TokenService, *, interceptors: Iterable[Interceptor]
),
function=service.revoke,
),
+ "/metalstack.admin.v2.TokenService/Create": Endpoint.unary(
+ method=MethodInfo(
+ name="Create",
+ service_name="metalstack.admin.v2.TokenService",
+ input=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest,
+ output=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ function=service.create,
+ ),
},
interceptors=interceptors,
read_max_bytes=read_max_bytes,
@@ -99,12 +112,34 @@ async def revoke(
timeout_ms=timeout_ms,
)
+ async def create(
+ self,
+ request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest,
+ *,
+ headers: Headers | Mapping[str, str] | None = None,
+ timeout_ms: int | None = None,
+ ) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse:
+ return await self.execute_unary(
+ request=request,
+ method=MethodInfo(
+ name="Create",
+ service_name="metalstack.admin.v2.TokenService",
+ input=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest,
+ output=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ headers=headers,
+ timeout_ms=timeout_ms,
+ )
+
class TokenServiceSync(Protocol):
def list(self, request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceListRequest, ctx: RequestContext) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceListResponse:
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
def revoke(self, request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceRevokeRequest, ctx: RequestContext) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceRevokeResponse:
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
+ def create(self, request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest, ctx: RequestContext) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse:
+ raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
class TokenServiceWSGIApplication(ConnectWSGIApplication):
@@ -131,6 +166,16 @@ def __init__(self, service: TokenServiceSync, interceptors: Iterable[Interceptor
),
function=service.revoke,
),
+ "/metalstack.admin.v2.TokenService/Create": EndpointSync.unary(
+ method=MethodInfo(
+ name="Create",
+ service_name="metalstack.admin.v2.TokenService",
+ input=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest,
+ output=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ function=service.create,
+ ),
},
interceptors=interceptors,
read_max_bytes=read_max_bytes,
@@ -182,3 +227,23 @@ def revoke(
headers=headers,
timeout_ms=timeout_ms,
)
+
+ def create(
+ self,
+ request: metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest,
+ *,
+ headers: Headers | Mapping[str, str] | None = None,
+ timeout_ms: int | None = None,
+ ) -> metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse:
+ return self.execute_unary(
+ request=request,
+ method=MethodInfo(
+ name="Create",
+ service_name="metalstack.admin.v2.TokenService",
+ input=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateRequest,
+ output=metalstack_dot_admin_dot_v2_dot_token__pb2.TokenServiceCreateResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ headers=headers,
+ timeout_ms=timeout_ms,
+ )
diff --git a/python/metalstack/admin/v2/token_pb2.py b/python/metalstack/admin/v2/token_pb2.py
index 2b3495b6..fcddc2cc 100644
--- a/python/metalstack/admin/v2/token_pb2.py
+++ b/python/metalstack/admin/v2/token_pb2.py
@@ -27,7 +27,7 @@
from metalstack.api.v2 import token_pb2 as metalstack_dot_api_dot_v2_dot_token__pb2
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmetalstack/admin/v2/token.proto\x12\x13metalstack.admin.v2\x1a\x1b\x62uf/validate/validate.proto\x1a\x1emetalstack/api/v2/common.proto\x1a\x1dmetalstack/api/v2/token.proto\";\n\x17TokenServiceListRequest\x12\x17\n\x04user\x18\x01 \x01(\tH\x00R\x04user\x88\x01\x01\x42\x07\n\x05_user\"L\n\x18TokenServiceListResponse\x12\x30\n\x06tokens\x18\x01 \x03(\x0b\x32\x18.metalstack.api.v2.TokenR\x06tokens\"Y\n\x19TokenServiceRevokeRequest\x12\x1c\n\x04uuid\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x04uuid\x12\x1e\n\x04user\x18\x02 \x01(\tB\n\xbaH\x07r\x05\x10\x02\x18\x80\x04R\x04user\"\x1c\n\x1aTokenServiceRevokeResponse2\xed\x01\n\x0cTokenService\x12k\n\x04List\x12,.metalstack.admin.v2.TokenServiceListRequest\x1a-.metalstack.admin.v2.TokenServiceListResponse\"\x06\xd2\xf3\x18\x02\x01\x02\x12p\n\x06Revoke\x12..metalstack.admin.v2.TokenServiceRevokeRequest\x1a/.metalstack.admin.v2.TokenServiceRevokeResponse\"\x05\xd2\xf3\x18\x01\x01\x42\xce\x01\n\x17\x63om.metalstack.admin.v2B\nTokenProtoP\x01Z9github.com/metal-stack/api/go/metalstack/admin/v2;adminv2\xa2\x02\x03MAX\xaa\x02\x13Metalstack.Admin.V2\xca\x02\x13Metalstack\\Admin\\V2\xe2\x02\x1fMetalstack\\Admin\\V2\\GPBMetadata\xea\x02\x15Metalstack::Admin::V2b\x06proto3')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmetalstack/admin/v2/token.proto\x12\x13metalstack.admin.v2\x1a\x1b\x62uf/validate/validate.proto\x1a\x1emetalstack/api/v2/common.proto\x1a\x1dmetalstack/api/v2/token.proto\";\n\x17TokenServiceListRequest\x12\x17\n\x04user\x18\x01 \x01(\tH\x00R\x04user\x88\x01\x01\x42\x07\n\x05_user\"L\n\x18TokenServiceListResponse\x12\x30\n\x06tokens\x18\x01 \x03(\x0b\x32\x18.metalstack.api.v2.TokenR\x06tokens\"Y\n\x19TokenServiceRevokeRequest\x12\x1c\n\x04uuid\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x04uuid\x12\x1e\n\x04user\x18\x02 \x01(\tB\n\xbaH\x07r\x05\x10\x02\x18\x80\x04R\x04user\"\x1c\n\x1aTokenServiceRevokeResponse\"y\n\x19TokenServiceCreateRequest\x12#\n\x04user\x18\x01 \x01(\tB\n\xbaH\x07r\x05\x10\x02\x18\x80\x04H\x00R\x04user\x88\x01\x01\x12.\n\x05token\x18\x02 \x01(\x0b\x32\x18.metalstack.api.v2.TokenR\x05tokenB\x07\n\x05_user\"d\n\x1aTokenServiceCreateResponse\x12.\n\x05token\x18\x01 \x01(\x0b\x32\x18.metalstack.api.v2.TokenR\x05token\x12\x16\n\x06secret\x18\x02 \x01(\tR\x06secret2\xdf\x02\n\x0cTokenService\x12k\n\x04List\x12,.metalstack.admin.v2.TokenServiceListRequest\x1a-.metalstack.admin.v2.TokenServiceListResponse\"\x06\xd2\xf3\x18\x02\x01\x02\x12p\n\x06Revoke\x12..metalstack.admin.v2.TokenServiceRevokeRequest\x1a/.metalstack.admin.v2.TokenServiceRevokeResponse\"\x05\xd2\xf3\x18\x01\x01\x12p\n\x06\x43reate\x12..metalstack.admin.v2.TokenServiceCreateRequest\x1a/.metalstack.admin.v2.TokenServiceCreateResponse\"\x05\xd2\xf3\x18\x01\x01\x42\xce\x01\n\x17\x63om.metalstack.admin.v2B\nTokenProtoP\x01Z9github.com/metal-stack/api/go/metalstack/admin/v2;adminv2\xa2\x02\x03MAX\xaa\x02\x13Metalstack.Admin.V2\xca\x02\x13Metalstack\\Admin\\V2\xe2\x02\x1fMetalstack\\Admin\\V2\\GPBMetadata\xea\x02\x15Metalstack::Admin::V2b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -39,10 +39,14 @@
_globals['_TOKENSERVICEREVOKEREQUEST'].fields_by_name['uuid']._serialized_options = b'\272H\005r\003\260\001\001'
_globals['_TOKENSERVICEREVOKEREQUEST'].fields_by_name['user']._loaded_options = None
_globals['_TOKENSERVICEREVOKEREQUEST'].fields_by_name['user']._serialized_options = b'\272H\007r\005\020\002\030\200\004'
+ _globals['_TOKENSERVICECREATEREQUEST'].fields_by_name['user']._loaded_options = None
+ _globals['_TOKENSERVICECREATEREQUEST'].fields_by_name['user']._serialized_options = b'\272H\007r\005\020\002\030\200\004'
_globals['_TOKENSERVICE'].methods_by_name['List']._loaded_options = None
_globals['_TOKENSERVICE'].methods_by_name['List']._serialized_options = b'\322\363\030\002\001\002'
_globals['_TOKENSERVICE'].methods_by_name['Revoke']._loaded_options = None
_globals['_TOKENSERVICE'].methods_by_name['Revoke']._serialized_options = b'\322\363\030\001\001'
+ _globals['_TOKENSERVICE'].methods_by_name['Create']._loaded_options = None
+ _globals['_TOKENSERVICE'].methods_by_name['Create']._serialized_options = b'\322\363\030\001\001'
_globals['_TOKENSERVICELISTREQUEST']._serialized_start=148
_globals['_TOKENSERVICELISTREQUEST']._serialized_end=207
_globals['_TOKENSERVICELISTRESPONSE']._serialized_start=209
@@ -51,6 +55,10 @@
_globals['_TOKENSERVICEREVOKEREQUEST']._serialized_end=376
_globals['_TOKENSERVICEREVOKERESPONSE']._serialized_start=378
_globals['_TOKENSERVICEREVOKERESPONSE']._serialized_end=406
- _globals['_TOKENSERVICE']._serialized_start=409
- _globals['_TOKENSERVICE']._serialized_end=646
+ _globals['_TOKENSERVICECREATEREQUEST']._serialized_start=408
+ _globals['_TOKENSERVICECREATEREQUEST']._serialized_end=529
+ _globals['_TOKENSERVICECREATERESPONSE']._serialized_start=531
+ _globals['_TOKENSERVICECREATERESPONSE']._serialized_end=631
+ _globals['_TOKENSERVICE']._serialized_start=634
+ _globals['_TOKENSERVICE']._serialized_end=985
# @@protoc_insertion_point(module_scope)
diff --git a/python/metalstack/admin/v2/token_pb2.pyi b/python/metalstack/admin/v2/token_pb2.pyi
index 9e47a5de..afd6aa1a 100644
--- a/python/metalstack/admin/v2/token_pb2.pyi
+++ b/python/metalstack/admin/v2/token_pb2.pyi
@@ -32,3 +32,19 @@ class TokenServiceRevokeRequest(_message.Message):
class TokenServiceRevokeResponse(_message.Message):
__slots__ = ()
def __init__(self) -> None: ...
+
+class TokenServiceCreateRequest(_message.Message):
+ __slots__ = ("user", "token")
+ USER_FIELD_NUMBER: _ClassVar[int]
+ TOKEN_FIELD_NUMBER: _ClassVar[int]
+ user: str
+ token: _token_pb2.Token
+ def __init__(self, user: _Optional[str] = ..., token: _Optional[_Union[_token_pb2.Token, _Mapping]] = ...) -> None: ...
+
+class TokenServiceCreateResponse(_message.Message):
+ __slots__ = ("token", "secret")
+ TOKEN_FIELD_NUMBER: _ClassVar[int]
+ SECRET_FIELD_NUMBER: _ClassVar[int]
+ token: _token_pb2.Token
+ secret: str
+ def __init__(self, token: _Optional[_Union[_token_pb2.Token, _Mapping]] = ..., secret: _Optional[str] = ...) -> None: ...