@@ -10,6 +10,7 @@ import (
1010
1111 "cloud.google.com/go/iam/admin/apiv1/adminpb"
1212 "github.com/googleapis/gax-go/v2/apierror"
13+ sdk "github.com/openshift-online/ocm-sdk-go"
1314 cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
1415 "github.com/pkg/errors"
1516 cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
@@ -26,6 +27,12 @@ const (
2627 IamApiRetrySeconds = 600
2728)
2829
30+ const (
31+ // PromQL time range in minutes
32+ newPoolUsageTimeRange = 5
33+ oldPoolUsageTimeRange = 2
34+ )
35+
2936const (
3037 impersonatorRole = "roles/iam.serviceAccountTokenCreator"
3138 workloadIdentityUserRole = "roles/iam.workloadIdentityUser"
@@ -43,6 +50,9 @@ type GcpClientWifConfigShim interface {
4350 DeleteServiceAccounts (ctx context.Context , log * log.Logger ) error
4451 DeleteWorkloadIdentityPool (ctx context.Context , log * log.Logger ) error
4552 UnbindServiceAccounts (ctx context.Context , log * log.Logger ) error
53+ HasAssociatedClusters (ctx context.Context , connection * sdk.Connection , wifConfigID string ) (bool , error )
54+ ValidateNewWifConfigPoolUsage (ctx context.Context , wifConfig * cmv1.WifConfig ) error
55+ ValidateOldWifConfigPoolUsage (ctx context.Context , wifConfig * cmv1.WifConfig ) error
4656}
4757
4858type shim struct {
@@ -1205,3 +1215,94 @@ func (c *shim) UnbindServiceAccounts(
12051215 }
12061216 return nil
12071217}
1218+
1219+ // checkPoolUsageWithQuery executes a PromQL query and returns true if any metric has a non-zero value
1220+ func (c * shim ) checkPoolUsageWithQuery (ctx context.Context , projectId string , query string ) (bool , error ) {
1221+ response , err := c .gcpClient .QueryPrometheusTimeSeries (ctx , projectId , query )
1222+ if err != nil {
1223+ return false , errors .Wrapf (err , "failed to execute prometheus query" )
1224+ }
1225+
1226+ // Check if the query was successful
1227+ if response .Status != "success" {
1228+ return false , errors .Errorf ("prometheus query failed with status: %s" , response .Status )
1229+ }
1230+
1231+ // Check if there are any results
1232+ if len (response .Data .Result ) == 0 {
1233+ return false , nil
1234+ }
1235+
1236+ // Check if any result has a non-zero value
1237+ for _ , result := range response .Data .Result {
1238+ value , err := result .GetFloatValue ()
1239+ if err != nil {
1240+ continue
1241+ }
1242+ if value > 0 {
1243+ return true , nil
1244+ }
1245+ }
1246+
1247+ return false , nil
1248+ }
1249+
1250+ // HasAssociatedClusters checks if a WIF config has any clusters associated with it
1251+ func (c * shim ) HasAssociatedClusters (
1252+ ctx context.Context ,
1253+ connection * sdk.Connection ,
1254+ wifConfigID string ,
1255+ ) (bool , error ) {
1256+ searchQuery := fmt .Sprintf ("gcp.authentication.wif_config_id = '%s'" , wifConfigID )
1257+ response , err := connection .ClustersMgmt ().V1 ().Clusters ().
1258+ List ().
1259+ Search (searchQuery ).
1260+ Send ()
1261+ if err != nil {
1262+ return false , errors .Wrapf (err , "failed to search for clusters using wif-config %s" , wifConfigID )
1263+ }
1264+
1265+ return response .Size () > 0 , nil
1266+ }
1267+
1268+ // ValidateNewWifConfigPoolUsage validates that a WIF config has recent pool usage
1269+ func (c * shim ) ValidateNewWifConfigPoolUsage (ctx context.Context , wifConfig * cmv1.WifConfig ) error {
1270+ projectId := wifConfig .Gcp ().FederatedProjectId ()
1271+ query := fmt .Sprintf (
1272+ WifQuery ,
1273+ wifConfig .Gcp ().WorkloadIdentityPool ().PoolId (),
1274+ newPoolUsageTimeRange ,
1275+ )
1276+
1277+ hasUsage , err := c .checkPoolUsageWithQuery (ctx , projectId , query )
1278+ if err != nil {
1279+ return errors .Wrapf (err , "failed to check workload identity pool usage" )
1280+ }
1281+
1282+ if ! hasUsage {
1283+ return errors .Errorf ("wif-config pool '%s' has no recent traffic" , wifConfig .Gcp ().WorkloadIdentityPool ().PoolId ())
1284+ }
1285+
1286+ return nil
1287+ }
1288+
1289+ // ValidateOldWifConfigPoolUsage validates if the old WIF config pool is still being used
1290+ func (c * shim ) ValidateOldWifConfigPoolUsage (ctx context.Context , wifConfig * cmv1.WifConfig ) error {
1291+ projectId := wifConfig .Gcp ().ProjectId ()
1292+ query := fmt .Sprintf (
1293+ WifQuery ,
1294+ wifConfig .Gcp ().WorkloadIdentityPool ().PoolId (),
1295+ oldPoolUsageTimeRange ,
1296+ )
1297+
1298+ hasUsage , err := c .checkPoolUsageWithQuery (ctx , projectId , query )
1299+ if err != nil {
1300+ return errors .Wrapf (err , "failed to check workload identity pool usage" )
1301+ }
1302+
1303+ if hasUsage {
1304+ return errors .Errorf ("wif-config pool '%s' is still being used" , wifConfig .Gcp ().WorkloadIdentityPool ().PoolId ())
1305+ }
1306+
1307+ return nil
1308+ }
0 commit comments