diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 66405e96b..4ae0afab8 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -45,6 +45,7 @@ import ( resourcesservicestorage "kubeops.dev/ui-server/pkg/registry/core/resourceservice" resourcesummarystorage "kubeops.dev/ui-server/pkg/registry/core/resourcesummary" coststorage "kubeops.dev/ui-server/pkg/registry/cost/reports" + "kubeops.dev/ui-server/pkg/registry/identity" clusteridstorage "kubeops.dev/ui-server/pkg/registry/identity/clusteridentity" inboxtokenreqstorage "kubeops.dev/ui-server/pkg/registry/identity/inboxtokenrequest" whoamistorage "kubeops.dev/ui-server/pkg/registry/identity/whoami" @@ -74,6 +75,7 @@ import ( fluxsrc "github.com/fluxcd/source-controller/api/v1" "github.com/graphql-go/handler" + "github.com/pkg/errors" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" openvizapi "go.openviz.dev/apimachinery/apis/openviz/v1alpha1" openvizcs "go.openviz.dev/apimachinery/client/clientset/versioned" @@ -350,7 +352,12 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(identityv1alpha1.GroupName, Scheme, metav1.ParameterCodec, Codecs) v1alpha1storage := map[string]rest.Storage{} - v1alpha1storage[identityv1alpha1.ResourceClusterIdentities] = clusteridstorage.NewStorage(ctrlClient) + + bc, err := identity.NewClient(c.ExtraConfig.BaseURL, c.ExtraConfig.Token, c.ExtraConfig.CACert) + if err != nil { + return nil, errors.Wrap(err, "failed to create b3 api client") + } + v1alpha1storage[identityv1alpha1.ResourceClusterIdentities] = clusteridstorage.NewStorage(ctrlClient, bc, cid) v1alpha1storage[identityv1alpha1.ResourceInboxTokenRequests] = inboxtokenreqstorage.NewStorage() v1alpha1storage[identityv1alpha1.ResourceWhoAmIs] = whoamistorage.NewStorage() apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage diff --git a/pkg/registry/identity/client.go b/pkg/registry/identity/client.go new file mode 100644 index 000000000..83af24d1c --- /dev/null +++ b/pkg/registry/identity/client.go @@ -0,0 +1,107 @@ +/* +Copyright AppsCode Inc. and Contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package identity + +import ( + "crypto/tls" + "crypto/x509" + "io" + "net/http" + "path" + + identityapi "kubeops.dev/ui-server/apis/identity/v1alpha1" + + "go.bytebuilders.dev/license-verifier/info" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" +) + +type Client struct { + baseURL string + token string + caCert []byte + client *http.Client +} + +func NewClient(baseURL, token string, caCert []byte) (*Client, error) { + c := &Client{ + baseURL: baseURL, + token: token, + caCert: caCert, + } + if len(caCert) == 0 { + c.client = http.DefaultClient + } else { + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + tlsConfig := &tls.Config{ + RootCAs: caCertPool, + } + transport := &http.Transport{TLSClientConfig: tlsConfig} + c.client = &http.Client{Transport: transport} + } + return c, nil +} + +func (c *Client) Identify(clusterUID string) (*identityapi.ClusterIdentityStatus, error) { + u, err := info.APIServerAddress(c.baseURL) + if err != nil { + return nil, err + } + u.Path = path.Join(u.Path, "api/v1/clusters", clusterUID) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + // add authorization header to the req + if c.token != "" { + req.Header.Add("Authorization", "Bearer "+c.token) + } + resp, err := c.client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, apierrors.NewGenericServerResponse( + resp.StatusCode, + http.MethodGet, + schema.GroupResource{Group: identityapi.GroupName, Resource: identityapi.ResourceClusterIdentities}, + "", + string(body), + 0, + false, + ) + } + + var ds identityapi.ClusterIdentityStatus + err = json.Unmarshal(body, &ds) + if err != nil { + return nil, err + } + return &ds, nil +} diff --git a/pkg/registry/identity/clusteridentity/storage.go b/pkg/registry/identity/clusteridentity/storage.go index ac91609b6..0a4d18c3a 100644 --- a/pkg/registry/identity/clusteridentity/storage.go +++ b/pkg/registry/identity/clusteridentity/storage.go @@ -21,6 +21,7 @@ import ( "strings" identityapi "kubeops.dev/ui-server/apis/identity/v1alpha1" + "kubeops.dev/ui-server/pkg/registry/identity" "gomodules.xyz/sync" core "k8s.io/api/core/v1" @@ -31,13 +32,14 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" "k8s.io/apiserver/pkg/registry/rest" - "kmodules.xyz/client-go/tools/clusterid" "sigs.k8s.io/controller-runtime/pkg/client" ) type Storage struct { - kc client.Client - convertor rest.TableConvertor + kc client.Client + bc *identity.Client + clusterUID string + convertor rest.TableConvertor identity *identityapi.ClusterIdentity once sync.Once @@ -55,9 +57,11 @@ var ( _ rest.SingularNameProvider = &Storage{} ) -func NewStorage(kc client.Client) *Storage { +func NewStorage(kc client.Client, bc *identity.Client, clusterUID string) *Storage { return &Storage{ - kc: kc, + kc: kc, + bc: bc, + clusterUID: clusterUID, convertor: rest.NewDefaultTableConvertor(schema.GroupResource{ Group: identityapi.GroupName, Resource: identityapi.ResourceClusterIdentities, @@ -101,7 +105,8 @@ func (r *Storage) knowThyself() { if err != nil { return err } - cm, err := clusterid.ClusterMetadataForNamespace(&ns) + + status, err := r.bc.Identify(r.clusterUID) if err != nil { return err } @@ -113,9 +118,7 @@ func (r *Storage) knowThyself() { CreationTimestamp: ns.CreationTimestamp, Generation: 1, }, - Status: identityapi.ClusterIdentityStatus{ - ClusterMetadata: *cm, - }, + Status: *status, } return nil })