void provisionAccess()

in sources/src/main/java/com/google/solutions/jitaccess/catalog/provisioning/Provisioner.java [377:453]


    void provisionAccess(
      @NotNull GroupId groupId,
      @NotNull Set<IamRoleBinding> roleBindings
    ) throws AccessException, IOException {

      var groupDetails = this.groupsClient.getGroup(groupId);

      var expectedChecksum = IamBindingChecksum.fromBindings(roleBindings);
      var actualChecksum = IamBindingChecksum.fromTaggedDescription(groupDetails.getDescription());

      if (actualChecksum.equals(expectedChecksum)) {
        //
        // The checksums match, indicating that the role bindings we provisioned
        // previously are still current.
        //
      }
      else {
        this.logger.info(
          EventIds.PROVISION_IAM_BINDINGS,
          "IAM role bindings for group %s have changed (expected checksum: %s, actual: %s), provisioning...",
          groupId,
          expectedChecksum,
          actualChecksum);

        //
        // One or more role bindings must have changed, so we need to
        // re-provision all bindings.
        //
        // If there are multiple roles for a single resource, we can
        // provision them at once.
        //
        var future = CompletableFutures.mapAsync(
          roleBindings
            .stream()
            .collect(Collectors.groupingBy(b -> b.resource()))
            .entrySet(),
          bindingsForResource -> {
            this.resourceManagerClient.modifyIamPolicy(
              bindingsForResource.getKey(),
              policy -> replaceBindingsForPrincipals(policy, groupId, bindingsForResource.getValue()),
              "Provisioning JIT group");
            return bindingsForResource.getKey();
          },
          this.executor);

        try {
          future.get();

          //
          // Update group.
          //
          this.groupsClient.patchGroup(
            new GroupKey(groupDetails.getName()),
            expectedChecksum.toTaggedDescription(groupDetails.getDescription()));

          this.logger.info(
            EventIds.PROVISION_IAM_BINDINGS,
            "IAM role bindings for group %s provisioned",
            groupId,
            expectedChecksum,
            actualChecksum);
        }
        catch (InterruptedException | ExecutionException e) {
          if (Exceptions.unwrap(e) instanceof AccessException accessException) {
            this.logger.error(
              EventIds.PROVISION_IAM_BINDINGS,
              String.format("Provisioning IAM role bindings for group %s failed", groupId),
              accessException);

            throw (AccessException) accessException.fillInStackTrace();
          }
          else {
            throw new UncheckedExecutionException(e);
          }
        }
      }
    }