From ad776a80065d3a90e2328b4a8d31fba8feb58bb2 Mon Sep 17 00:00:00 2001 From: Aaron Crickenberger Date: Fri, 24 Jul 2020 13:52:33 -0700 Subject: [PATCH 1/2] Create a prow.viewer custom org role I want to empower others to see and troubleshoot whatever resources constraints (or lack thereof) the release-blocking jobs are running under Members of the k8s-infra-prow-viewers@kubernetes.io get this role on projects related to prow The role is a composite of: - roles/compute.viewer - roles/container.viewer - roles/logging.viewer - roles/monitoring.view It's defined by a file and will be updated anytime infra/gcp/ensure-e2e-projects.sh is run I've currently manually created it and applied it to the k8s-infra-prow-build project to verify access to expected resources --- .../k8s-infra-prow-build/prow-build/main.tf | 8 + infra/gcp/ensure-e2e-projects.sh | 8 +- infra/gcp/lib.sh | 36 ++ infra/gcp/roles/prow.viewer.yaml | 325 ++++++++++++++++++ 4 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 infra/gcp/roles/prow.viewer.yaml diff --git a/infra/gcp/clusters/projects/k8s-infra-prow-build/prow-build/main.tf b/infra/gcp/clusters/projects/k8s-infra-prow-build/prow-build/main.tf index 6e9cdab98a3..2ccabc676b0 100644 --- a/infra/gcp/clusters/projects/k8s-infra-prow-build/prow-build/main.tf +++ b/infra/gcp/clusters/projects/k8s-infra-prow-build/prow-build/main.tf @@ -46,6 +46,14 @@ resource "google_project_iam_member" "k8s_infra_prow_oncall" { member = "group:k8s-infra-prow-oncall@kubernetes.io" } +// Ensure k8s-infra-prow-viewers@kuberentes.io has prow.viewer access to this project +resource "google_project_iam_member" "k8s_infra_prow_viewers" { + project = local.project_id + # TODO: use data resource to get org role name instead of hardcode + role = "organizations/758905017065/roles/prow.viewer" + member = "group:k8s-infra-prow-viewers@kubernetes.io" +} + // Create GCP SA for pods resource "google_service_account" "prow_build_cluster_sa" { project = local.project_id diff --git a/infra/gcp/ensure-e2e-projects.sh b/infra/gcp/ensure-e2e-projects.sh index f40f0f69d0b..3f7ca41a1ba 100755 --- a/infra/gcp/ensure-e2e-projects.sh +++ b/infra/gcp/ensure-e2e-projects.sh @@ -32,6 +32,12 @@ function usage() { echo > /dev/stderr } +## setup custom role for prow troubleshooting +color 6 "Ensuring custom org role prow.viewer role exists" +( + ensure_custom_org_role_from_file "prow.viewer" "${SCRIPT_DIR}/roles/prow.viewer.yaml" +) 2>&1 | indent + ## setup service accounts and ips for the prow build cluster PROW_BUILD_SVCACCT=$(svc_acct_email "k8s-infra-prow-build" "prow-build") @@ -133,7 +139,7 @@ for prj; do gcloud \ projects add-iam-policy-binding "${prj}" \ --member "group:k8s-infra-prow-viewers@kubernetes.io" \ - --role roles/viewer + --role $(custom_org_role_name "prow.viewer") if [[ "${prj}" =~ k8s-infra-e2e.*scale ]]; then color 6 "Empower k8s-infra-sig-scalability-oncall@kubernetes.io to admin e2e project: ${prj}" diff --git a/infra/gcp/lib.sh b/infra/gcp/lib.sh index 33360ecc0fe..6a71c0c3db0 100755 --- a/infra/gcp/lib.sh +++ b/infra/gcp/lib.sh @@ -610,3 +610,39 @@ function ensure_custom_iam_role() { --permissions "${permissions}" fi } + +# Ensure that custom IAM role exists and is in sync with definition in file +# Arguments: +# $1: The role name (e.g. "prow.viewer") +# $2: The file (e.g. "/path/to/file.yaml") +function ensure_custom_org_role_from_file() { + if [ ! $# -eq 2 -o -z "$1" -o -z "$2" ]; then + echo "ensure_custom_org_role_from_file(name, file) requires 2 arguments" >&2 + return 1 + fi + + local org="${GCP_ORG}" + local name="${1}" + local file="${2}" + + if ! gcloud iam roles describe "${name}" --organization "${org}" \ + >/dev/null 2>&1 + then + # be noisy when creating a role + gcloud iam roles create "${name}" --organization "${org}" --file "${file}" + else + # be quiet when updating, only output name of role + gcloud iam roles update "${name}" --organization "${org}" --file "${file}" | grep ^name: + fi +} + +function custom_org_role_name() { + if [ ! $# -eq 1 -o -z "$1" ]; then + echo "custom_org_role_name(name) requires 1 arguments" >&2 + return 1 + fi + + local name="${1}" + + echo "organizations/${GCP_ORG}/roles/${name}" +} diff --git a/infra/gcp/roles/prow.viewer.yaml b/infra/gcp/roles/prow.viewer.yaml new file mode 100644 index 00000000000..d1842ee64a1 --- /dev/null +++ b/infra/gcp/roles/prow.viewer.yaml @@ -0,0 +1,325 @@ +title: Prow Viewer +description: View access to services for troubleshooting prow +stage: ALPHA +includedPermissions: +- resourcemanager.projects.get +- resourcemanager.projects.list +# roles/compute.viewer +- compute.acceleratorTypes.get +- compute.acceleratorTypes.list +- compute.addresses.get +- compute.addresses.list +- compute.autoscalers.get +- compute.autoscalers.list +- compute.backendBuckets.get +- compute.backendBuckets.list +- compute.backendServices.get +- compute.backendServices.list +- compute.commitments.get +- compute.commitments.list +- compute.diskTypes.get +- compute.diskTypes.list +- compute.disks.get +- compute.disks.getIamPolicy +- compute.disks.list +- compute.externalVpnGateways.get +- compute.externalVpnGateways.list +- compute.firewalls.get +- compute.firewalls.list +- compute.forwardingRules.get +- compute.forwardingRules.list +- compute.globalAddresses.get +- compute.globalAddresses.list +- compute.globalForwardingRules.get +- compute.globalForwardingRules.list +- compute.globalOperations.get +- compute.globalOperations.getIamPolicy +- compute.globalOperations.list +- compute.globalPublicDelegatedPrefixes.get +- compute.globalPublicDelegatedPrefixes.list +- compute.healthChecks.get +- compute.healthChecks.list +- compute.httpHealthChecks.get +- compute.httpHealthChecks.list +- compute.httpsHealthChecks.get +- compute.httpsHealthChecks.list +- compute.images.get +- compute.images.getFromFamily +- compute.images.getIamPolicy +- compute.images.list +- compute.instanceGroupManagers.get +- compute.instanceGroupManagers.list +- compute.instanceGroups.get +- compute.instanceGroups.list +- compute.instanceTemplates.get +- compute.instanceTemplates.getIamPolicy +- compute.instanceTemplates.list +- compute.instances.get +- compute.instances.getEffectiveFirewalls +- compute.instances.getGuestAttributes +- compute.instances.getIamPolicy +- compute.instances.getScreenshot +- compute.instances.getSerialPortOutput +- compute.instances.getShieldedInstanceIdentity +- compute.instances.getShieldedVmIdentity +- compute.instances.list +- compute.instances.listReferrers +- compute.interconnectAttachments.get +- compute.interconnectAttachments.list +- compute.interconnectLocations.get +- compute.interconnectLocations.list +- compute.interconnects.get +- compute.interconnects.list +- compute.licenseCodes.get +- compute.licenseCodes.getIamPolicy +- compute.licenseCodes.list +- compute.licenses.get +- compute.licenses.getIamPolicy +- compute.licenses.list +- compute.machineTypes.get +- compute.machineTypes.list +- compute.maintenancePolicies.get +- compute.maintenancePolicies.getIamPolicy +- compute.maintenancePolicies.list +- compute.networkEndpointGroups.get +- compute.networkEndpointGroups.getIamPolicy +- compute.networkEndpointGroups.list +- compute.networks.get +- compute.networks.getEffectiveFirewalls +- compute.networks.list +- compute.networks.listPeeringRoutes +- compute.nodeGroups.get +- compute.nodeGroups.getIamPolicy +- compute.nodeGroups.list +- compute.nodeTemplates.get +- compute.nodeTemplates.getIamPolicy +- compute.nodeTemplates.list +- compute.nodeTypes.get +- compute.nodeTypes.list +- compute.organizations.listAssociations +- compute.projects.get +- compute.publicAdvertisedPrefixes.get +- compute.publicAdvertisedPrefixes.list +- compute.publicDelegatedPrefixes.get +- compute.publicDelegatedPrefixes.list +- compute.regionBackendServices.get +- compute.regionBackendServices.list +- compute.regionHealthCheckServices.get +- compute.regionHealthCheckServices.list +- compute.regionNotificationEndpoints.get +- compute.regionNotificationEndpoints.list +- compute.regionOperations.get +- compute.regionOperations.getIamPolicy +- compute.regionOperations.list +- compute.regions.get +- compute.regions.list +- compute.reservations.get +- compute.reservations.list +- compute.resourcePolicies.get +- compute.resourcePolicies.list +- compute.routers.get +- compute.routers.list +- compute.routes.get +- compute.routes.list +- compute.securityPolicies.get +- compute.securityPolicies.getIamPolicy +- compute.securityPolicies.list +- compute.snapshots.get +- compute.snapshots.getIamPolicy +- compute.snapshots.list +- compute.sslCertificates.get +- compute.sslCertificates.list +- compute.sslPolicies.get +- compute.sslPolicies.list +- compute.sslPolicies.listAvailableFeatures +- compute.subnetworks.get +- compute.subnetworks.getIamPolicy +- compute.subnetworks.list +- compute.targetHttpProxies.get +- compute.targetHttpProxies.list +- compute.targetHttpsProxies.get +- compute.targetHttpsProxies.list +- compute.targetInstances.get +- compute.targetInstances.list +- compute.targetPools.get +- compute.targetPools.list +- compute.targetSslProxies.get +- compute.targetSslProxies.list +- compute.targetTcpProxies.get +- compute.targetTcpProxies.list +- compute.targetVpnGateways.get +- compute.targetVpnGateways.list +- compute.urlMaps.get +- compute.urlMaps.list +- compute.urlMaps.validate +- compute.vpnGateways.get +- compute.vpnGateways.list +- compute.vpnTunnels.get +- compute.vpnTunnels.list +- compute.zoneOperations.get +- compute.zoneOperations.getIamPolicy +- compute.zoneOperations.list +- compute.zones.get +- compute.zones.list +- resourcemanager.projects.get +- resourcemanager.projects.list +- serviceusage.quotas.get +- serviceusage.services.get +- serviceusage.services.list +# roles/container.viewer +- container.apiServices.get +- container.apiServices.list +- container.backendConfigs.get +- container.backendConfigs.list +- container.bindings.get +- container.bindings.list +- container.certificateSigningRequests.get +- container.certificateSigningRequests.list +- container.clusterRoleBindings.get +- container.clusterRoleBindings.list +- container.clusterRoles.get +- container.clusterRoles.list +- container.clusters.get +- container.clusters.list +- container.componentStatuses.get +- container.componentStatuses.list +- container.configMaps.get +- container.configMaps.list +- container.controllerRevisions.get +- container.controllerRevisions.list +- container.cronJobs.get +- container.cronJobs.getStatus +- container.cronJobs.list +- container.csiDrivers.get +- container.csiDrivers.list +- container.csiNodes.get +- container.csiNodes.list +- container.customResourceDefinitions.get +- container.customResourceDefinitions.list +- container.daemonSets.get +- container.daemonSets.getStatus +- container.daemonSets.list +- container.deployments.get +- container.deployments.getStatus +- container.deployments.list +- container.endpoints.get +- container.endpoints.list +- container.events.get +- container.events.list +- container.horizontalPodAutoscalers.get +- container.horizontalPodAutoscalers.getStatus +- container.horizontalPodAutoscalers.list +- container.ingresses.get +- container.ingresses.getStatus +- container.ingresses.list +- container.initializerConfigurations.get +- container.initializerConfigurations.list +- container.jobs.get +- container.jobs.getStatus +- container.jobs.list +- container.limitRanges.get +- container.limitRanges.list +- container.namespaces.get +- container.namespaces.getStatus +- container.namespaces.list +- container.networkPolicies.get +- container.networkPolicies.list +- container.nodes.get +- container.nodes.getStatus +- container.nodes.list +- container.operations.get +- container.operations.list +- container.persistentVolumeClaims.get +- container.persistentVolumeClaims.getStatus +- container.persistentVolumeClaims.list +- container.persistentVolumes.get +- container.persistentVolumes.getStatus +- container.persistentVolumes.list +- container.petSets.get +- container.petSets.list +- container.podDisruptionBudgets.get +- container.podDisruptionBudgets.getStatus +- container.podDisruptionBudgets.list +- container.podPresets.get +- container.podPresets.list +- container.podSecurityPolicies.get +- container.podSecurityPolicies.list +- container.podTemplates.get +- container.podTemplates.list +- container.pods.get +- container.pods.getStatus +- container.pods.list +- container.replicaSets.get +- container.replicaSets.getScale +- container.replicaSets.getStatus +- container.replicaSets.list +- container.replicationControllers.get +- container.replicationControllers.getScale +- container.replicationControllers.getStatus +- container.replicationControllers.list +- container.resourceQuotas.get +- container.resourceQuotas.getStatus +- container.resourceQuotas.list +- container.roleBindings.get +- container.roleBindings.list +- container.roles.get +- container.roles.list +- container.runtimeClasses.get +- container.runtimeClasses.list +- container.scheduledJobs.get +- container.scheduledJobs.list +- container.serviceAccounts.get +- container.serviceAccounts.list +- container.services.get +- container.services.getStatus +- container.services.list +- container.statefulSets.get +- container.statefulSets.getStatus +- container.statefulSets.list +- container.storageClasses.get +- container.storageClasses.list +- container.thirdPartyObjects.get +- container.thirdPartyObjects.list +- container.thirdPartyResources.get +- container.thirdPartyResources.list +- container.tokenReviews.create +# roles/logging.viewer +- logging.buckets.get +- logging.buckets.list +- logging.exclusions.get +- logging.exclusions.list +- logging.logEntries.list +- logging.logMetrics.get +- logging.logMetrics.list +- logging.logServiceIndexes.list +- logging.logServices.list +- logging.logs.list +- logging.sinks.get +- logging.sinks.list +- logging.usage.get +# roles/monitoring.viewer +- cloudnotifications.activities.list +- monitoring.alertPolicies.get +- monitoring.alertPolicies.list +- monitoring.dashboards.get +- monitoring.dashboards.list +- monitoring.groups.get +- monitoring.groups.list +- monitoring.metricDescriptors.get +- monitoring.metricDescriptors.list +- monitoring.monitoredResourceDescriptors.get +- monitoring.monitoredResourceDescriptors.list +- monitoring.notificationChannelDescriptors.get +- monitoring.notificationChannelDescriptors.list +- monitoring.notificationChannels.get +- monitoring.notificationChannels.list +- monitoring.publicWidgets.get +- monitoring.publicWidgets.list +- monitoring.services.get +- monitoring.services.list +- monitoring.slos.get +- monitoring.slos.list +- monitoring.timeSeries.list +- monitoring.uptimeCheckConfigs.get +- monitoring.uptimeCheckConfigs.list +- stackdriver.projects.get From 2fb1f5568827cac443b04091474a4787d08101ce Mon Sep 17 00:00:00 2001 From: Aaron Crickenberger Date: Fri, 24 Jul 2020 14:09:50 -0700 Subject: [PATCH 2/2] Add roles/container.clusterViewer to prow.viewer --- infra/gcp/roles/prow.viewer.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/infra/gcp/roles/prow.viewer.yaml b/infra/gcp/roles/prow.viewer.yaml index d1842ee64a1..fd11f77c7f5 100644 --- a/infra/gcp/roles/prow.viewer.yaml +++ b/infra/gcp/roles/prow.viewer.yaml @@ -166,6 +166,9 @@ includedPermissions: - serviceusage.quotas.get - serviceusage.services.get - serviceusage.services.list +# roles/container.clusterViewer +- container.clusters.get +- container.clusters.list # roles/container.viewer - container.apiServices.get - container.apiServices.list