I am searching for an example, which shows, how to make google cloud run service (in google cloud platform) public or non-public (switch between the two) programmatically. The best would be using JAVA API (probably for GCP AIM).
Background: I'd like to be able to quickly enable/disable (i.e. make accessible/inaccessible) my Google Cloud Run services. Ultimately the code could reside in some Google Cloud Function and disable the services as a reaction on some event, but as a first shot, it is OK, if the code is running locally and I need to manually authenticate with my account by Google.
The documentation of Google Cloud Run tells, that it is impossible to disable the service, but one can make it "non-public" which in certain sense would have similar effect (https://cloud.google.com/run/docs/managing/services#disable).
Cloud Run does not offer a direct way to make a service stop serving traffic, but you can achieve a similar result by revoking the permission to invoke the service to identities that are invoking the service. Notably, if your service is "public", remove allUsers from the Cloud Run Invoker role (roles/run.invoker).
I am new to GCP, so unfortunately this "simple" action does not look that simple to me. I would appreciate any information in this regard or at best, example, which shows, how to do it.
Orienting myself to the answer from John and after further looking around in the internet and GCP docs I ended up with this solution, which works for me:
package your.package.name;
import com.google.cloud.run.v2.Service;
import com.google.cloud.run.v2.ServiceName;
import com.google.cloud.run.v2.ServicesClient;
import com.google.iam.v1.*;
import com.google.protobuf.ProtocolStringList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args) throws IOException {
// For it to work locally we need to provide credentials.
// See here: https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to
try (final ServicesClient servicesClient = ServicesClient.create()) {
// Define service name
final var projectName = "your-gcp-project-name";
final var location = "us-central1"; // change to the location of your service
final var serviceNameString = "your-cloud-run-service-name";
final ServiceName serviceName = ServiceName.of(projectName, location, serviceNameString);
// Get current (aka "old" policy) policy for the cervice
final GetIamPolicyRequest getIamPolicyRequest = GetIamPolicyRequest.newBuilder()
.setResource(serviceName.toString())
.setOptions(GetPolicyOptions.newBuilder().build())
.build();
final Policy oldPolicy = servicesClient.getIamPolicy(getIamPolicyRequest);
final List<Binding> oldBindings = oldPolicy.getBindingsList();
// Check bindings of old policy. Copy them to the new Policy object.
// If the binding contains role and member, which we want to exclud, then
// don't include the member into the binding for corresponding role
// (or exclude the binding all together)
final String invokerRole = "roles/run.invoker";
final String allUsersMember = "allUsers";
final List<Binding> newBindings = new ArrayList<>();
boolean bindingWasChanged = false;
for (var oldBinding : oldBindings) {
if (oldBinding.getRole().equals(invokerRole)) {
ProtocolStringList membersList = oldBinding.getMembersList();
if (membersList.contains(allUsersMember)) {
final List<String> filteredMembers = membersList.stream().filter(m -> !allUsersMember.equals(m)).toList();
if (!filteredMembers.isEmpty()) {
final Binding newBinding = Binding.newBuilder(oldBinding).clearMembers().addAllMembers(filteredMembers).build();
newBindings.add(newBinding);
}
// else just skip the binding
bindingWasChanged = true;
} else {
newBindings.add(oldBinding);
}
} else {
newBindings.add(oldBinding);
}
}
// If we changed the list of bindings, replace service policy with the new one we just created.
// Note, hat there is no method to modify policy in place, but only to replace the whole object.
if (bindingWasChanged) {
final Policy newPolicy = Policy.newBuilder(oldPolicy).clearBindings().addAllBindings(newBindings).build();
final SetIamPolicyRequest setIamPolicyRequest = SetIamPolicyRequest.newBuilder()
.setResource(serviceName.toString())
.setPolicy(newPolicy)
.build();
final Policy updatedPolicy = servicesClient.setIamPolicy(setIamPolicyRequest);
} else {
System.out.println("No bindings were changed (no binding for given role was found or it does not have given member).");
}
}
}
}
Dependencies from build.gradle:
dependencies {
implementation(enforcedPlatform("com.google.cloud:libraries-bom:26.18.0"))
implementation 'com.google.cloud:google-cloud-run' // :0.20.0
}
Here are also some links: