Skip to content

Commit ba6ce0e

Browse files
AlexTugarevroboquat
authored andcommitted
[public-api] Implement CreateClientConfig
1 parent 1f31c21 commit ba6ce0e

File tree

3 files changed

+105
-15
lines changed

3 files changed

+105
-15
lines changed

components/public-api-server/pkg/apiv1/oidc.go

+40-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
connect "github.com/bufbuild/connect-go"
1313
"github.com/gitpod-io/gitpod/common-go/experiments"
1414
"github.com/gitpod-io/gitpod/common-go/log"
15+
iam "github.com/gitpod-io/gitpod/components/iam-api/go/v1"
1516
v1 "github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1"
1617
"github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1/v1connect"
1718
protocol "github.com/gitpod-io/gitpod/gitpod-protocol"
@@ -20,16 +21,18 @@ import (
2021
"github.com/google/uuid"
2122
)
2223

23-
func NewOIDCService(connPool proxy.ServerConnectionPool, expClient experiments.Client) *OIDCService {
24+
func NewOIDCService(connPool proxy.ServerConnectionPool, expClient experiments.Client, oidcService iam.OIDCServiceClient) *OIDCService {
2425
return &OIDCService{
2526
connectionPool: connPool,
2627
expClient: expClient,
28+
oidcService: oidcService,
2729
}
2830
}
2931

3032
type OIDCService struct {
3133
expClient experiments.Client
3234
connectionPool proxy.ServerConnectionPool
35+
oidcService iam.OIDCServiceClient
3336

3437
v1connect.UnimplementedOIDCServiceHandler
3538
}
@@ -45,7 +48,42 @@ func (s *OIDCService) CreateClientConfig(ctx context.Context, req *connect.Reque
4548
return nil, err
4649
}
4750

48-
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("gitpod.experimental.v1.OIDCService.CreateClientConfig is not implemented"))
51+
result, err := s.oidcService.CreateClientConfig(ctx, &iam.CreateClientConfigRequest{
52+
Config: papiConfigToIAM(req.Msg.GetConfig()),
53+
})
54+
if err != nil {
55+
// todo@at fix error handling
56+
return nil, connect.NewError(connect.CodeInternal, err)
57+
}
58+
59+
return connect.NewResponse(&v1.CreateClientConfigResponse{
60+
Config: iamConfigToPAPI(result.GetConfig()),
61+
}), nil
62+
}
63+
64+
func papiConfigToIAM(c *v1.OIDCClientConfig) *iam.OIDCClientConfig {
65+
return &iam.OIDCClientConfig{
66+
OidcConfig: &iam.OIDCConfig{
67+
Issuer: c.OidcConfig.GetIssuer(),
68+
},
69+
Oauth2Config: &iam.OAuth2Config{
70+
ClientId: c.GetOauth2Config().GetClientId(),
71+
ClientSecret: c.GetOauth2Config().GetClientSecret(),
72+
},
73+
}
74+
}
75+
func iamConfigToPAPI(c *iam.OIDCClientConfig) *v1.OIDCClientConfig {
76+
return &v1.OIDCClientConfig{
77+
Id: c.GetId(),
78+
OidcConfig: &v1.OIDCConfig{
79+
Issuer: c.OidcConfig.GetIssuer(),
80+
},
81+
Oauth2Config: &v1.OAuth2Config{
82+
ClientId: c.GetOauth2Config().GetClientId(),
83+
ClientSecret: "REDACTED",
84+
},
85+
CreationTime: c.GetCreationTime(),
86+
}
4987
}
5088

5189
func (s *OIDCService) GetClientConfig(ctx context.Context, req *connect.Request[v1.GetClientConfigRequest]) (*connect.Response[v1.GetClientConfigResponse], error) {

components/public-api-server/pkg/apiv1/oidc_test.go

+48-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import (
1010
"net/http/httptest"
1111
"testing"
1212

13+
"google.golang.org/grpc/codes"
14+
"google.golang.org/grpc/status"
15+
16+
grpc "google.golang.org/grpc"
17+
18+
iam "github.com/gitpod-io/gitpod/components/iam-api/go/v1"
19+
1320
connect "github.com/bufbuild/connect-go"
1421
"github.com/gitpod-io/gitpod/common-go/experiments"
1522
"github.com/gitpod-io/gitpod/common-go/experiments/experimentstest"
@@ -37,7 +44,7 @@ var (
3744
)
3845

3946
func TestOIDCService_CreateClientConfig(t *testing.T) {
40-
t.Run("feature flag disabled returns unathorized", func(t *testing.T) {
47+
t.Run("feature flag disabled returns unauthorized", func(t *testing.T) {
4148
serverMock, client := setupOIDCService(t, withOIDCFeatureDisabled)
4249

4350
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
@@ -48,19 +55,29 @@ func TestOIDCService_CreateClientConfig(t *testing.T) {
4855
require.Equal(t, connect.CodePermissionDenied, connect.CodeOf(err))
4956
})
5057

51-
t.Run("feature flag enabled returns unimplemented", func(t *testing.T) {
58+
t.Run("feature flag enabled returns created config", func(t *testing.T) {
5259
serverMock, client := setupOIDCService(t, withOIDCFeatureEnabled)
5360

5461
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
5562

56-
_, err := client.CreateClientConfig(context.Background(), connect.NewRequest(&v1.CreateClientConfigRequest{}))
57-
require.Error(t, err)
58-
require.Equal(t, connect.CodeUnimplemented, connect.CodeOf(err))
63+
config := &v1.OIDCClientConfig{
64+
OidcConfig: &v1.OIDCConfig{Issuer: "test-issuer"},
65+
Oauth2Config: &v1.OAuth2Config{ClientId: "test-id", ClientSecret: "test-secret"},
66+
}
67+
response, err := client.CreateClientConfig(context.Background(), connect.NewRequest(&v1.CreateClientConfigRequest{
68+
Config: config,
69+
}))
70+
require.NoError(t, err)
71+
require.NotNil(t, response)
72+
config.Oauth2Config.ClientSecret = "REDACTED"
73+
requireEqualProto(t, &v1.CreateClientConfigResponse{
74+
Config: config,
75+
}, response.Msg)
5976
})
6077
}
6178

6279
func TestOIDCService_GetClientConfig(t *testing.T) {
63-
t.Run("feature flag disabled returns unathorized", func(t *testing.T) {
80+
t.Run("feature flag disabled returns unauthorized", func(t *testing.T) {
6481
serverMock, client := setupOIDCService(t, withOIDCFeatureDisabled)
6582

6683
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
@@ -83,7 +100,7 @@ func TestOIDCService_GetClientConfig(t *testing.T) {
83100
}
84101

85102
func TestOIDCService_ListClientConfigs(t *testing.T) {
86-
t.Run("feature flag disabled returns unathorized", func(t *testing.T) {
103+
t.Run("feature flag disabled returns unauthorized", func(t *testing.T) {
87104
serverMock, client := setupOIDCService(t, withOIDCFeatureDisabled)
88105

89106
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
@@ -106,7 +123,7 @@ func TestOIDCService_ListClientConfigs(t *testing.T) {
106123
}
107124

108125
func TestOIDCService_UpdateClientConfig(t *testing.T) {
109-
t.Run("feature flag disabled returns unathorized", func(t *testing.T) {
126+
t.Run("feature flag disabled returns unauthorized", func(t *testing.T) {
110127
serverMock, client := setupOIDCService(t, withOIDCFeatureDisabled)
111128

112129
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
@@ -129,7 +146,7 @@ func TestOIDCService_UpdateClientConfig(t *testing.T) {
129146
}
130147

131148
func TestOIDCService_DeleteClientConfig(t *testing.T) {
132-
t.Run("feature flag disabled returns unathorized", func(t *testing.T) {
149+
t.Run("feature flag disabled returns unauthorized", func(t *testing.T) {
133150
serverMock, client := setupOIDCService(t, withOIDCFeatureDisabled)
134151

135152
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
@@ -159,7 +176,7 @@ func setupOIDCService(t *testing.T, expClient experiments.Client) (*protocol.Moc
159176

160177
serverMock := protocol.NewMockAPIInterface(ctrl)
161178

162-
svc := NewOIDCService(&FakeServerConnPool{api: serverMock}, expClient)
179+
svc := NewOIDCService(&FakeServerConnPool{api: serverMock}, expClient, &stubOIDCServiceServer{})
163180

164181
_, handler := v1connect.NewOIDCServiceHandler(svc, connect.WithInterceptors(auth.NewServerInterceptor()))
165182

@@ -172,3 +189,24 @@ func setupOIDCService(t *testing.T, expClient experiments.Client) (*protocol.Moc
172189

173190
return serverMock, client
174191
}
192+
193+
type stubOIDCServiceServer struct {
194+
}
195+
196+
func (stubOIDCServiceServer) CreateClientConfig(ctx context.Context, request *iam.CreateClientConfigRequest, options ...grpc.CallOption) (*iam.CreateClientConfigResponse, error) {
197+
return &iam.CreateClientConfigResponse{
198+
Config: request.GetConfig(),
199+
}, nil
200+
}
201+
func (stubOIDCServiceServer) GetClientConfig(context.Context, *iam.GetClientConfigRequest, ...grpc.CallOption) (*iam.GetClientConfigResponse, error) {
202+
return nil, status.Errorf(codes.Unimplemented, "method GetClientConfig not implemented")
203+
}
204+
func (stubOIDCServiceServer) ListClientConfigs(context.Context, *iam.ListClientConfigsRequest, ...grpc.CallOption) (*iam.ListClientConfigsResponse, error) {
205+
return nil, status.Errorf(codes.Unimplemented, "method ListClientConfigs not implemented")
206+
}
207+
func (stubOIDCServiceServer) UpdateClientConfig(context.Context, *iam.UpdateClientConfigRequest, ...grpc.CallOption) (*iam.UpdateClientConfigResponse, error) {
208+
return nil, status.Errorf(codes.Unimplemented, "method UpdateClientConfig not implemented")
209+
}
210+
func (stubOIDCServiceServer) DeleteClientConfig(context.Context, *iam.DeleteClientConfigRequest, ...grpc.CallOption) (*iam.DeleteClientConfigResponse, error) {
211+
return nil, status.Errorf(codes.Unimplemented, "method DeleteClientConfig not implemented")
212+
}

components/public-api-server/pkg/server/server.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import (
1616
"github.com/gitpod-io/gitpod/common-go/log"
1717
"gorm.io/gorm"
1818

19+
grpc "google.golang.org/grpc"
20+
"google.golang.org/grpc/credentials/insecure"
21+
22+
iam "github.com/gitpod-io/gitpod/components/iam-api/go/v1"
1923
"github.com/gitpod-io/gitpod/components/public-api/go/config"
2024
"github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1/v1connect"
2125
"github.com/gorilla/handlers"
@@ -33,6 +37,10 @@ import (
3337
func Start(logger *logrus.Entry, version string, cfg *config.Configuration) error {
3438
logger.WithField("config", cfg).Info("Starting public-api.")
3539

40+
if cfg.OIDCServiceAddress == "" {
41+
return fmt.Errorf("`oidcServiceAddress` is missing in config")
42+
}
43+
3644
gitpodAPI, err := url.Parse(cfg.GitpodServiceURL)
3745
if err != nil {
3846
return fmt.Errorf("failed to parse Gitpod API URL: %w", err)
@@ -92,7 +100,13 @@ func Start(logger *logrus.Entry, version string, cfg *config.Configuration) erro
92100

93101
srv.HTTPMux().Handle("/stripe/invoices/webhook", handlers.ContentTypeHandler(stripeWebhookHandler, "application/json"))
94102

95-
if registerErr := register(srv, connPool, expClient, dbConn, signer); registerErr != nil {
103+
conn, err := grpc.Dial(cfg.OIDCServiceAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
104+
if err != nil {
105+
return fmt.Errorf("failed to dial oidc service gRPC server: %w", err)
106+
}
107+
var oidcService = iam.NewOIDCServiceClient(conn)
108+
109+
if registerErr := register(srv, connPool, expClient, dbConn, signer, oidcService); registerErr != nil {
96110
return fmt.Errorf("failed to register services: %w", registerErr)
97111
}
98112

@@ -103,7 +117,7 @@ func Start(logger *logrus.Entry, version string, cfg *config.Configuration) erro
103117
return nil
104118
}
105119

106-
func register(srv *baseserver.Server, connPool proxy.ServerConnectionPool, expClient experiments.Client, dbConn *gorm.DB, signer auth.Signer) error {
120+
func register(srv *baseserver.Server, connPool proxy.ServerConnectionPool, expClient experiments.Client, dbConn *gorm.DB, signer auth.Signer, oidcService iam.OIDCServiceClient) error {
107121
proxy.RegisterMetrics(srv.MetricsRegistry())
108122

109123
connectMetrics := NewConnectMetrics()
@@ -140,7 +154,7 @@ func register(srv *baseserver.Server, connPool proxy.ServerConnectionPool, expCl
140154
projectsRoute, projectsServiceHandler := v1connect.NewProjectsServiceHandler(apiv1.NewProjectsService(connPool), handlerOptions...)
141155
srv.HTTPMux().Handle(projectsRoute, projectsServiceHandler)
142156

143-
oidcRoute, oidcServiceHandler := v1connect.NewOIDCServiceHandler(apiv1.NewOIDCService(connPool, expClient), handlerOptions...)
157+
oidcRoute, oidcServiceHandler := v1connect.NewOIDCServiceHandler(apiv1.NewOIDCService(connPool, expClient, oidcService), handlerOptions...)
144158
srv.HTTPMux().Handle(oidcRoute, oidcServiceHandler)
145159

146160
return nil

0 commit comments

Comments
 (0)