Repository: mrsked/mrsk
File: lib/kamal/secrets/adapters/gcp_secret_manager.rb (Ruby)

Code before:
      #
      # Some valid examples:
      # - "my-user@example.com" sets the user
      # - "my-user@example.com,my-service-user@example.com" will use my-user and enable service account impersonation as my-service-user
      # - "default" will use the default user and no impersonation
      # - "default,my-service-user@example.com" will use the default user, and enable service account impersonation as my-service-user
      # - "default,my-service-user@example.com,another-service-user@example.com" same as above, but with an impersonation delegation chain

      if !logged_in?
        raise RuntimeError, "gcloud is not authenticated, please run `gcloud auth login`"
      end

      user, impersonate_service_account = parse_account(account)

      {
        user: user,
        impersonate_service_account: impersonate_service_account
      }
    end

    def fetch_secrets(secrets, account:, session:)
      # puts("secrets spec: #{secrets.inspect}")
      {}.tap do |results|
        secrets_with_metadata(secrets).each do |secret, metadata|
          project, secret_name, secret_version = metadata
          item_name = project == "default" ? secret_name : "#{project}/#{secret_name}"
          results[item_name] = fetch_secret(session, project, secret_name, secret_version)
          raise RuntimeError, "Could not read #{item_name} from Google Secret Manager" unless $?.success?
        end
      end
    end

    def fetch_secret(session, project, secret_name, secret_version)
      secret = run_command("secrets versions access #{secret_version} --secret=#{secret_name.shellescape}", session: session, project: project)
      Base64.decode64(secret.dig("payload", "data"))
    end

    # The secret needs to at least contain a secret name, but project name, and secret version can also be specified.
    #
    # The string "default" can be used to refer to the default project configured for gcloud.
    #
    # The version can be either the string "latest", or a version number.
    #
    # The following formats are valid:
    #
    # - The following are all equivalent, and sets project: default, secret name: my-secret, version: latest
    #   - "my-secret"
    #   - "default/my-secret"
    #   - "default/my-secret/latest"
    #   - "my-secret/latest" in combination with --from=default
    # - "my-secret/123" (only in combination with --from=some-project) -> project: some-project, secret name: my-secret, version: 123

Review comment (security):
I think we can leave the `default` in here. If you do `kamal secret extract` will still find the secret if you tell it to look for <secret_name> without the prefix.

Code after:
      #
      # Some valid examples:
      # - "my-user@example.com" sets the user
      # - "my-user@example.com|my-service-user@example.com" will use my-user and enable service account impersonation as my-service-user
      # - "default" will use the default user and no impersonation
      # - "default|my-service-user@example.com" will use the default user, and enable service account impersonation as my-service-user
      # - "default|my-service-user@example.com,another-service-user@example.com" same as above, but with an impersonation delegation chain

      if !logged_in?
        `gcloud auth login`
        raise RuntimeError, "gcloud is not authenticated, please run `gcloud auth login`" if !logged_in?
      end

      nil
    end

    def fetch_secrets(secrets, account:, session:)
      user, service_account = parse_account(account)

      {}.tap do |results|
        secrets_with_metadata(secrets).each do |secret, (project, secret_name, secret_version)|
          item_name = "#{project}/#{secret_name}"
          results[item_name] = fetch_secret(project, secret_name, secret_version, user, service_account)
          raise RuntimeError, "Could not read #{item_name} from Google Secret Manager" unless $?.success?
        end
      end
    end

    def fetch_secret(project, secret_name, secret_version, user, service_account)
      secret = run_command(
        "secrets versions access #{secret_version.shellescape} --secret=#{secret_name.shellescape}",
        project: project,
        user: user,
        service_account: service_account
      )
      Base64.decode64(secret.dig("payload", "data"))
    end

    # The secret needs to at least contain a secret name, but project name, and secret version can also be specified.
    #
    # The string "default" can be used to refer to the default project configured for gcloud.
    #
    # The version can be either the string "latest", or a version number.
    #
    # The following formats are valid:
    #
    # - The following are all equivalent, and sets project: default, secret name: my-secret, version: latest
    #   - "my-secret"
    #   - "default/my-secret"
    #   - "default/my-secret/latest"
    #   - "my-secret/latest" in combination with --from=default