Skip to content

Commit abf8950

Browse files
committed
feat: retrieve identity service server
1 parent e7b3cf5 commit abf8950

File tree

5 files changed

+139
-3
lines changed

5 files changed

+139
-3
lines changed

cloud/scope/clients.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,34 @@ func newComputeService(ctx context.Context, credentialsRef *infrav1.ObjectRefere
103103
return computeSvc, nil
104104
}
105105

106+
func newTargetPoolsClient(ctx context.Context, credentialsRef *infrav1.ObjectReference, crClient client.Client) (*computerest.TargetPoolsClient, error) {
107+
opts, err := defaultClientOptions(ctx, credentialsRef, crClient)
108+
if err != nil {
109+
return nil, fmt.Errorf("getting default gcp client options: %w", err)
110+
}
111+
112+
targetPoolsClient, err := computerest.NewTargetPoolsRESTClient(ctx, opts...)
113+
if err != nil {
114+
return nil, errors.Errorf("failed to create target pools client: %v", err)
115+
}
116+
117+
return targetPoolsClient, nil
118+
}
119+
120+
func newForwardingRulesClient(ctx context.Context, credentialsRef *infrav1.ObjectReference, crClient client.Client) (*computerest.ForwardingRulesClient, error) {
121+
opts, err := defaultClientOptions(ctx, credentialsRef, crClient)
122+
if err != nil {
123+
return nil, fmt.Errorf("getting default gcp client options: %w", err)
124+
}
125+
126+
forwardingRulesClient, err := computerest.NewForwardingRulesRESTClient(ctx, opts...)
127+
if err != nil {
128+
return nil, errors.Errorf("failed to create gcp forwarding rules client: %v", err)
129+
}
130+
131+
return forwardingRulesClient, nil
132+
}
133+
106134
func newClusterManagerClient(ctx context.Context, credentialsRef *infrav1.ObjectReference, crClient client.Client) (*container.ClusterManagerClient, error) {
107135
opts, err := defaultClientOptions(ctx, credentialsRef, crClient)
108136
if err != nil {

cloud/scope/managedcontrolplane.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"sigs.k8s.io/cluster-api/util/conditions"
2626

27+
compute "cloud.google.com/go/compute/apiv1"
2728
container "cloud.google.com/go/container/apiv1"
2829
credentials "cloud.google.com/go/iam/credentials/apiv1"
2930
resourcemanager "cloud.google.com/go/resourcemanager/apiv3"
@@ -43,6 +44,8 @@ const (
4344
// ManagedControlPlaneScopeParams defines the input parameters used to create a new Scope.
4445
type ManagedControlPlaneScopeParams struct {
4546
CredentialsClient *credentials.IamCredentialsClient
47+
TargetPoolsClient *compute.TargetPoolsClient
48+
ForwardingRulesClient *compute.ForwardingRulesClient
4649
ManagedClusterClient *container.ClusterManagerClient
4750
TagBindingsClient *resourcemanager.TagBindingsClient
4851
Client client.Client
@@ -69,12 +72,19 @@ func NewManagedControlPlaneScope(ctx context.Context, params ManagedControlPlane
6972
return nil, fmt.Errorf("getting gcp credentials: %w", err)
7073
}
7174

75+
if params.TargetPoolsClient == nil {
76+
targetPoolsClient, err := newTargetPoolsClient(ctx, params.GCPManagedCluster.Spec.CredentialsRef, params.Client)
77+
if err != nil {
78+
return nil, errors.Errorf("failed to create gcp target pools client: %v", err)
79+
}
80+
params.TargetPoolsClient = targetPoolsClient
81+
}
7282
if params.ManagedClusterClient == nil {
73-
managedClusterClient, err := newClusterManagerClient(ctx, params.GCPManagedCluster.Spec.CredentialsRef, params.Client)
83+
forwardingRulesClient, err := newForwardingRulesClient(ctx, params.GCPManagedCluster.Spec.CredentialsRef, params.Client)
7484
if err != nil {
75-
return nil, errors.Errorf("failed to create gcp managed cluster client: %v", err)
85+
return nil, errors.Errorf("failed to create gcp forwarding rules client: %v", err)
7686
}
77-
params.ManagedClusterClient = managedClusterClient
87+
params.ForwardingRulesClient = forwardingRulesClient
7888
}
7989
if params.TagBindingsClient == nil {
8090
tagBindingsClient, err := newTagBindingsClient(ctx, params.GCPManagedCluster.Spec.CredentialsRef, params.Client, params.GCPManagedCluster.Spec.Region)
@@ -102,6 +112,8 @@ func NewManagedControlPlaneScope(ctx context.Context, params ManagedControlPlane
102112
Cluster: params.Cluster,
103113
GCPManagedCluster: params.GCPManagedCluster,
104114
GCPManagedControlPlane: params.GCPManagedControlPlane,
115+
tpClient: params.TargetPoolsClient,
116+
frClient: params.ForwardingRulesClient,
105117
mcClient: params.ManagedClusterClient,
106118
tagBindingsClient: params.TagBindingsClient,
107119
credentialsClient: params.CredentialsClient,
@@ -118,6 +130,8 @@ type ManagedControlPlaneScope struct {
118130
Cluster *clusterv1.Cluster
119131
GCPManagedCluster *infrav1exp.GCPManagedCluster
120132
GCPManagedControlPlane *infrav1exp.GCPManagedControlPlane
133+
tpClient *compute.TargetPoolsClient
134+
frClient *compute.ForwardingRulesClient
121135
mcClient *container.ClusterManagerClient
122136
tagBindingsClient *resourcemanager.TagBindingsClient
123137
credentialsClient *credentials.IamCredentialsClient
@@ -142,6 +156,8 @@ func (s *ManagedControlPlaneScope) PatchObject() error {
142156

143157
// Close closes the current scope persisting the managed control plane configuration and status.
144158
func (s *ManagedControlPlaneScope) Close() error {
159+
s.tpClient.Close()
160+
s.frClient.Close()
145161
s.mcClient.Close()
146162
s.tagBindingsClient.Close()
147163
s.credentialsClient.Close()
@@ -158,6 +174,16 @@ func (s *ManagedControlPlaneScope) Client() client.Client {
158174
return s.client
159175
}
160176

177+
// TargetPoolsClient returns a client used to interact with google compute target pools.
178+
func (s *ManagedControlPlaneScope) TargetPoolsClient() *compute.TargetPoolsClient {
179+
return s.tpClient
180+
}
181+
182+
// ForwardingRulesClient returns a client used to interact with google compute forwarding rules.
183+
func (s *ManagedControlPlaneScope) ForwardingRulesClient() *compute.ForwardingRulesClient {
184+
return s.frClient
185+
}
186+
161187
// ManagedControlPlaneClient returns a client used to interact with GKE.
162188
func (s *ManagedControlPlaneScope) ManagedControlPlaneClient() *container.ClusterManagerClient {
163189
return s.mcClient

cloud/services/container/clusters/reconcile.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ package clusters
1818

1919
import (
2020
"context"
21+
"errors"
2122
"fmt"
2223
"strings"
2324

25+
"sigs.k8s.io/cluster-api-provider-gcp/cloud/providerid"
2426
"sigs.k8s.io/cluster-api-provider-gcp/cloud/scope"
2527
"sigs.k8s.io/cluster-api-provider-gcp/cloud/services/shared"
2628

29+
"cloud.google.com/go/compute/apiv1/computepb"
2730
"cloud.google.com/go/container/apiv1/containerpb"
2831
"github.com/go-logr/logr"
2932
"github.com/google/go-cmp/cmp"
@@ -166,6 +169,13 @@ func (s *Service) Reconcile(ctx context.Context) (ctrl.Result, error) {
166169
return ctrl.Result{}, err
167170
}
168171

172+
identityServiceServer, err := s.getIdentityServiceServer(ctx, &log)
173+
if err != nil {
174+
log.Error(err, "Failed to retrieve identity service server")
175+
} else if identityServiceServer != "" {
176+
s.scope.GCPManagedControlPlane.Status.IdentityServiceServer = identityServiceServer
177+
}
178+
169179
s.scope.SetEndpoint(cluster.GetEndpoint())
170180
conditions.MarkTrue(s.scope.ConditionSetter(), clusterv1.ReadyCondition)
171181
conditions.MarkTrue(s.scope.ConditionSetter(), infrav1exp.GKEControlPlaneReadyCondition)
@@ -482,3 +492,67 @@ func compareMasterAuthorizedNetworksConfig(a, b *containerpb.MasterAuthorizedNet
482492
}
483493
return true
484494
}
495+
496+
func (s *Service) getIdentityServiceServer(ctx context.Context, log *logr.Logger) (string, error) {
497+
if s.scope.GCPManagedControlPlane.Spec.EnableIdentityService == nil || !*s.scope.GCPManagedControlPlane.Spec.EnableIdentityService {
498+
// Identity service is not enabled, return empty string
499+
return "", nil
500+
}
501+
502+
nodePools, _, err := s.scope.GetAllNodePools(ctx)
503+
if err != nil {
504+
return "", err
505+
}
506+
const (
507+
indentityServiceFilter = "description:anthos-identity-service"
508+
instanceFilterFormat = "instance:https://www.googleapis.com/compute/v1/projects/%s/zones/%s/instances/%s"
509+
)
510+
511+
instanceFilters := []string{}
512+
for _, np := range nodePools {
513+
for _, providerID := range np.Spec.ProviderIDList {
514+
parsedProviderID, err := providerid.NewFromResourceURL(providerID)
515+
if err != nil {
516+
return "", err
517+
}
518+
instanceFilters = append(instanceFilters, fmt.Sprintf(instanceFilterFormat, parsedProviderID.Project, parsedProviderID.Location, parsedProviderID.Name))
519+
}
520+
}
521+
522+
if len(instanceFilters) == 0 {
523+
return "", errors.New("no instances found")
524+
}
525+
526+
targetPoolName := ""
527+
req := &computepb.ListTargetPoolsRequest{Filter: indentityServiceFilter + " AND (" + strings.Join(instanceFilters, " OR ") + ")"}
528+
for resp, err := range s.scope.TargetPoolsClient().List(ctx, req).All() {
529+
if err != nil {
530+
return "", err
531+
} else if targetPoolName != "" {
532+
return "", errors.New("multiple target pools found")
533+
}
534+
targetPoolName = resp.Name
535+
}
536+
identityServer := ""
537+
nameFilter := "name:" + targetPoolName
538+
req := &computepb.ListForwardingRulesRequest{Filter: instanceFilter + " AND " + nameFilter}
539+
for resp, err := range s.scope.ForwardingRulesClient().List(ctx, req).All() {
540+
if err != nil {
541+
return err
542+
} else if identityServer != "" {
543+
return "", errors.New("multiple forwarding rules found")
544+
} else if len(resp.Ports) != 1 {
545+
return "", fmt.Errorf("unexpected ports count in forwarding rule: %d", len(resp.Ports))
546+
} else if resp.Ports[0] != "443" {
547+
return "", fmt.Errorf("unexpected port in forwarding rule: %d", resp.Ports[0])
548+
}
549+
550+
return "https://" + resp.IPAddress + ":" + resp.Ports[0], nil
551+
}
552+
553+
if identityServer == "" {
554+
return "", errors.New("no forwarding rules found")
555+
}
556+
557+
return identityServer, nil
558+
}

config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ spec:
259259
- type
260260
type: object
261261
type: array
262+
identityServiceServer:
263+
description: identityServiceServer indicates the server for external authentication
264+
when the identity service is enabled.
265+
type: boolean
262266
currentVersion:
263267
description: CurrentVersion shows the current version of the GKE control
264268
plane.

exp/api/v1beta1/gcpmanagedcontrolplane_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ type GCPManagedControlPlaneStatus struct {
171171
// CurrentVersion shows the current version of the GKE control plane.
172172
// +optional
173173
CurrentVersion string `json:"currentVersion,omitempty"`
174+
175+
// IdentityServiceServer shows the server of anthos indentify service when enabled.
176+
// +optional
177+
IdentityServiceServer string `json:"identityServiceServer,omitempty"`
174178
}
175179

176180
// +kubebuilder:object:root=true

0 commit comments

Comments
 (0)